Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

iio: accel: adxl380: Add support for 1 kHz sampling frequency

In sensor variants (such as ADXL380 and ADXL382) that support low-power
mode, the SAR signal path allows sampling acceleration data at lower rates;
more specifically, when the sensor operates in VLP mode, the sampling
frequency is 1 kHz.

To add support for the 1kHz sampling frequency value, modify the operating
mode selection logic to take into account the sampling frequency, and
configure the decimation filters only when applicable (i.e. when using a
sampling frequency that relies on the DSM signal path); in addition,
constrain the available sampling frequency values based on whether the
sensor is operating in low-power mode.

Signed-off-by: Francesco Lavra <flavra@baylibre.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Francesco Lavra and committed by
Jonathan Cameron
f65de31f fabae755

+71 -22
+62 -21
drivers/iio/accel/adxl380.c
··· 266 266 267 267 /* 268 268 * Activity/Inactivity detection available only in VLP/ULP 269 - * mode and for devices that support low power modes. Otherwise 270 - * go straight to measure mode (same bits as ADXL380_OP_MODE_HP). 269 + * mode and for devices that support low power modes. 271 270 */ 272 271 if (act_inact_enabled) 272 + st->odr = ADXL380_ODR_VLP; 273 + 274 + if (st->odr == ADXL380_ODR_VLP) 273 275 op_mode = ADXL380_OP_MODE_VLP; 274 276 else 275 277 op_mode = ADXL380_OP_MODE_HP; ··· 499 497 if (ret) 500 498 return ret; 501 499 502 - ret = regmap_update_bits(st->regmap, ADXL380_TRIG_CFG_REG, 503 - ADXL380_TRIG_CFG_DEC_2X_MSK, 504 - FIELD_PREP(ADXL380_TRIG_CFG_DEC_2X_MSK, odr & 1)); 505 - if (ret) 506 - return ret; 500 + if (odr >= ADXL380_ODR_DSM) { 501 + u8 mul = odr - ADXL380_ODR_DSM; 502 + u8 field; 507 503 508 - ret = regmap_update_bits(st->regmap, ADXL380_TRIG_CFG_REG, 509 - ADXL380_TRIG_CFG_SINC_RATE_MSK, 510 - FIELD_PREP(ADXL380_TRIG_CFG_SINC_RATE_MSK, odr >> 1)); 511 - if (ret) 512 - return ret; 504 + field = FIELD_PREP(ADXL380_TRIG_CFG_DEC_2X_MSK, mul & 1); 505 + ret = regmap_update_bits(st->regmap, ADXL380_TRIG_CFG_REG, 506 + ADXL380_TRIG_CFG_DEC_2X_MSK, field); 507 + if (ret) 508 + return ret; 509 + 510 + field = FIELD_PREP(ADXL380_TRIG_CFG_SINC_RATE_MSK, mul >> 1); 511 + ret = regmap_update_bits(st->regmap, ADXL380_TRIG_CFG_REG, 512 + ADXL380_TRIG_CFG_SINC_RATE_MSK, field); 513 + if (ret) 514 + return ret; 515 + } 513 516 514 517 st->odr = odr; 515 518 ret = adxl380_set_measure_en(st, true); ··· 1155 1148 .predisable = adxl380_buffer_predisable, 1156 1149 }; 1157 1150 1151 + static int adxl380_samp_freq_avail(struct adxl380_state *st, const int **vals, 1152 + int *length) 1153 + { 1154 + bool act_inact_enabled; 1155 + int ret; 1156 + 1157 + if (!st->chip_info->has_low_power) { 1158 + *vals = st->chip_info->samp_freq_tbl + ADXL380_ODR_DSM; 1159 + *length = ADXL380_ODR_MAX - ADXL380_ODR_DSM; 1160 + return 0; 1161 + } 1162 + 1163 + ret = adxl380_act_inact_enabled(st, &act_inact_enabled); 1164 + if (ret) 1165 + return 0; 1166 + 1167 + /* 1168 + * Motion detection is only functional in low-power mode, and this 1169 + * affects the available sampling frequencies. 1170 + */ 1171 + *vals = st->chip_info->samp_freq_tbl; 1172 + *length = act_inact_enabled ? ADXL380_ODR_DSM : ADXL380_ODR_MAX; 1173 + 1174 + return 0; 1175 + } 1176 + 1158 1177 static int adxl380_read_raw(struct iio_dev *indio_dev, 1159 1178 struct iio_chan_spec const *chan, 1160 1179 int *val, int *val2, long info) ··· 1261 1228 long mask) 1262 1229 { 1263 1230 struct adxl380_state *st = iio_priv(indio_dev); 1231 + int ret; 1264 1232 1265 1233 if (chan->type != IIO_ACCEL) 1266 1234 return -EINVAL; ··· 1273 1239 *length = ARRAY_SIZE(st->chip_info->scale_tbl) * 2; 1274 1240 return IIO_AVAIL_LIST; 1275 1241 case IIO_CHAN_INFO_SAMP_FREQ: 1276 - *vals = (const int *)st->chip_info->samp_freq_tbl; 1242 + ret = adxl380_samp_freq_avail(st, vals, length); 1243 + if (ret) 1244 + return ret; 1245 + 1277 1246 *type = IIO_VAL_INT; 1278 - *length = ARRAY_SIZE(st->chip_info->samp_freq_tbl); 1279 1247 return IIO_AVAIL_LIST; 1280 1248 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 1281 1249 *vals = (const int *)st->lpf_tbl; ··· 1300 1264 int val, int val2, long info) 1301 1265 { 1302 1266 struct adxl380_state *st = iio_priv(indio_dev); 1303 - int odr_index, lpf_index, hpf_index, range_index; 1267 + const int *freq_vals; 1268 + int odr_index, lpf_index, hpf_index, range_index, freq_count, ret; 1304 1269 1305 1270 switch (info) { 1306 1271 case IIO_CHAN_INFO_SAMP_FREQ: 1307 - odr_index = adxl380_find_match_1d_tbl(st->chip_info->samp_freq_tbl, 1308 - ARRAY_SIZE(st->chip_info->samp_freq_tbl), 1272 + ret = adxl380_samp_freq_avail(st, &freq_vals, &freq_count); 1273 + if (ret) 1274 + return ret; 1275 + 1276 + odr_index = adxl380_find_match_1d_tbl(freq_vals, freq_count, 1309 1277 val); 1310 1278 return adxl380_set_odr(st, odr_index); 1311 1279 case IIO_CHAN_INFO_CALIBBIAS: ··· 1671 1631 [ADXL380_OP_MODE_8G_RANGE] = { 0, 2615434 }, 1672 1632 [ADXL380_OP_MODE_16G_RANGE] = { 0, 5229886 }, 1673 1633 }, 1674 - .samp_freq_tbl = { 8000, 16000, 32000 }, 1634 + .samp_freq_tbl = { 0, 8000, 16000, 32000 }, 1675 1635 /* 1676 1636 * The datasheet defines an intercept of 550 LSB at 25 degC 1677 1637 * and a sensitivity of 10.2 LSB/C. ··· 1689 1649 [ADXL382_OP_MODE_30G_RANGE] = { 0, 9806650 }, 1690 1650 [ADXL382_OP_MODE_60G_RANGE] = { 0, 19613300 }, 1691 1651 }, 1692 - .samp_freq_tbl = { 16000, 32000, 64000 }, 1652 + .samp_freq_tbl = { 0, 16000, 32000, 64000 }, 1693 1653 /* 1694 1654 * The datasheet defines an intercept of 550 LSB at 25 degC 1695 1655 * and a sensitivity of 10.2 LSB/C. ··· 1707 1667 [ADXL380_OP_MODE_8G_RANGE] = { 0, 2615434 }, 1708 1668 [ADXL380_OP_MODE_16G_RANGE] = { 0, 5229886 }, 1709 1669 }, 1710 - .samp_freq_tbl = { 8000, 16000, 32000 }, 1670 + .samp_freq_tbl = { 1000, 8000, 16000, 32000 }, 1711 1671 /* 1712 1672 * The datasheet defines an intercept of 470 LSB at 25 degC 1713 1673 * and a sensitivity of 10.2 LSB/C. ··· 1727 1687 [ADXL382_OP_MODE_30G_RANGE] = { 0, 9806650 }, 1728 1688 [ADXL382_OP_MODE_60G_RANGE] = { 0, 19613300 }, 1729 1689 }, 1730 - .samp_freq_tbl = { 16000, 32000, 64000 }, 1690 + .samp_freq_tbl = { 1000, 16000, 32000, 64000 }, 1731 1691 /* 1732 1692 * The datasheet defines an intercept of 570 LSB at 25 degC 1733 1693 * and a sensitivity of 10.2 LSB/C. ··· 1966 1926 st->dev = dev; 1967 1927 st->regmap = regmap; 1968 1928 st->chip_info = chip_info; 1929 + st->odr = ADXL380_ODR_DSM; 1969 1930 1970 1931 mutex_init(&st->lock); 1971 1932
+9 -1
drivers/iio/accel/adxl380.h
··· 8 8 #ifndef _ADXL380_H_ 9 9 #define _ADXL380_H_ 10 10 11 + enum adxl380_odr { 12 + ADXL380_ODR_VLP, 13 + ADXL380_ODR_DSM, 14 + ADXL380_ODR_DSM_2X, 15 + ADXL380_ODR_DSM_4X, 16 + ADXL380_ODR_MAX 17 + }; 18 + 11 19 struct adxl380_chip_info { 12 20 const char *name; 13 21 const int scale_tbl[3][2]; 14 - const int samp_freq_tbl[3]; 22 + const int samp_freq_tbl[ADXL380_ODR_MAX]; 15 23 const struct iio_info *info; 16 24 const int temp_offset; 17 25 const u16 chip_id;