summaryrefslogtreecommitdiff
path: root/drivers/iio/imu
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-04-26 11:14:21 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2021-04-26 11:14:21 -0700
commit8900d92fd666d936a7bfb4c567ac26736a414fb4 (patch)
tree19c37bab5adc8d40d825cb629edf0e8a337955a2 /drivers/iio/imu
parentc01c0716ccf5db2086d9693033472f37de96a699 (diff)
parentc295d3007ff63064181befa734d9705dfc10b396 (diff)
Merge tag 'staging-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging/IIO driver updates from Greg KH: "Here is the big set of staging and IIO driver updates for 5.13-rc1. Lots of little churn in here, and some larger churn as well. Major things are: - removal of wimax drivers, no one has this hardware anymore for this failed "experiment". - removal of the Google gasket driver, turns out no one wanted to maintain it or cares about it anymore, so they asked for it to be removed. - comedi finally moves out of the staging directory into drivers/comedi This is one of the oldest kernel subsystems around, being created in the 2.0 kernel days, and was one of the first things added to drivers/staging/ when that was created over 15 years ago. It should have been moved out of staging a long time ago, it's well maintained and used by loads of different devices in the real world every day. Nice to see this finally happen. - so many tiny coding style cleanups it's not funny. Perfect storm of at least 2 different intern project application deadlines combined to provide a huge number of new contributions in this area from people learning how to do kernel development. Great job to everyone involved here. There's also the normal updates for IIO drivers with new IIO drivers and updates all over that subsystem. All of these have been in linux-next for a while with no reported issues" * tag 'staging-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (907 commits) staging: octeon: Use 'for_each_child_of_node' Staging: rtl8723bs: rtw_xmit: fixed tabbing issue staging: rtl8188eu: remove unused function parameters staging: rtl8188eu: cmdThread is a task_struct staging: rtl8188eu: remove constant variable and dead code staging: rtl8188eu: change bLeisurePs' type to bool staging: rtl8723bs: remove empty #ifdef block staging: rtl8723bs: remove unused DBG_871X_LEVEL macro declarations staging: rtl8723bs: split too long line staging: rtl8723bs: fix indentation in if block staging: rtl8723bs: fix code indent issue staging: rtl8723bs: replace DBG_871X_LEVEL logs with netdev_*() staging: rtl8192e: indent statement properly staging: rtl8723bs: Remove led_blink_hdl() and everything related staging: comedi: move out of staging directory staging: rtl8723bs: remove sdio_drv_priv structure staging: rtl8723bs: remove unused argument in function staging: rtl8723bs: remove DBG_871X_SEL_NL macro declaration staging: rtl8723bs: replace DBG_871X_SEL_NL with netdev_dbg() staging: rtl8723bs: fix indentation issue introduced by long line split ...
Diffstat (limited to 'drivers/iio/imu')
-rw-r--r--drivers/iio/imu/adis16400.c22
-rw-r--r--drivers/iio/imu/adis16460.c4
-rw-r--r--drivers/iio/imu/adis16475.c123
-rw-r--r--drivers/iio/imu/adis16480.c133
-rw-r--r--drivers/iio/imu/adis_trigger.c21
-rw-r--r--drivers/iio/imu/fxos8700_i2c.c3
-rw-r--r--drivers/iio/imu/fxos8700_spi.c3
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c14
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c13
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c72
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c10
-rw-r--r--drivers/iio/imu/kmx61.c1
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c15
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c3
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c3
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c3
16 files changed, 288 insertions, 155 deletions
diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c
index 785a4ce606d8..768aa493a1a6 100644
--- a/drivers/iio/imu/adis16400.c
+++ b/drivers/iio/imu/adis16400.c
@@ -504,7 +504,6 @@ static int adis16400_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int val, int val2, long info)
{
struct adis16400_state *st = iio_priv(indio_dev);
- struct mutex *slock = &st->adis.state_lock;
int ret, sps;
switch (info) {
@@ -517,18 +516,18 @@ static int adis16400_write_raw(struct iio_dev *indio_dev,
* Need to cache values so we can update if the frequency
* changes.
*/
- mutex_lock(slock);
+ adis_dev_lock(&st->adis);
st->filt_int = val;
/* Work out update to current value */
sps = st->variant->get_freq(st);
if (sps < 0) {
- mutex_unlock(slock);
+ adis_dev_unlock(&st->adis);
return sps;
}
ret = __adis16400_set_filter(indio_dev, sps,
val * 1000 + val2 / 1000);
- mutex_unlock(slock);
+ adis_dev_unlock(&st->adis);
return ret;
case IIO_CHAN_INFO_SAMP_FREQ:
sps = val * 1000 + val2 / 1000;
@@ -536,9 +535,9 @@ static int adis16400_write_raw(struct iio_dev *indio_dev,
if (sps <= 0)
return -EINVAL;
- mutex_lock(slock);
+ adis_dev_lock(&st->adis);
ret = st->variant->set_freq(st, sps);
- mutex_unlock(slock);
+ adis_dev_unlock(&st->adis);
return ret;
default:
return -EINVAL;
@@ -549,7 +548,6 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long info)
{
struct adis16400_state *st = iio_priv(indio_dev);
- struct mutex *slock = &st->adis.state_lock;
int16_t val16;
int ret;
@@ -605,17 +603,17 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
*val = st->variant->temp_offset;
return IIO_VAL_INT;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
- mutex_lock(slock);
+ adis_dev_lock(&st->adis);
/* Need both the number of taps and the sampling frequency */
ret = __adis_read_reg_16(&st->adis,
ADIS16400_SENS_AVG,
&val16);
if (ret) {
- mutex_unlock(slock);
+ adis_dev_unlock(&st->adis);
return ret;
}
ret = st->variant->get_freq(st);
- mutex_unlock(slock);
+ adis_dev_unlock(&st->adis);
if (ret)
return ret;
ret /= adis16400_3db_divisors[val16 & 0x07];
@@ -623,9 +621,9 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
*val2 = (ret % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ:
- mutex_lock(slock);
+ adis_dev_lock(&st->adis);
ret = st->variant->get_freq(st);
- mutex_unlock(slock);
+ adis_dev_unlock(&st->adis);
if (ret)
return ret;
*val = ret / 1000;
diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c
index 74a161e39733..73bf45e859b8 100644
--- a/drivers/iio/imu/adis16460.c
+++ b/drivers/iio/imu/adis16460.c
@@ -403,12 +403,12 @@ static int adis16460_probe(struct spi_device *spi)
if (ret)
return ret;
+ /* We cannot mask the interrupt, so ensure it isn't auto enabled */
+ st->adis.irq_flag |= IRQF_NO_AUTOEN;
ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL);
if (ret)
return ret;
- adis16460_enable_irq(&st->adis, 0);
-
ret = __adis_initial_startup(&st->adis);
if (ret)
return ret;
diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c
index 197d48240991..1de62fc79e0f 100644
--- a/drivers/iio/imu/adis16475.c
+++ b/drivers/iio/imu/adis16475.c
@@ -17,6 +17,8 @@
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/irq.h>
+#include <linux/lcm.h>
+#include <linux/math.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/property.h>
@@ -101,6 +103,7 @@ struct adis16475 {
u32 clk_freq;
bool burst32;
unsigned long lsb_flag;
+ u16 sync_mode;
/* Alignment needed for the timestamp */
__be16 data[ADIS16475_MAX_SCAN_DATA] __aligned(8);
};
@@ -117,6 +120,11 @@ enum {
ADIS16475_SCAN_CRC_FAILURE,
};
+static bool low_rate_allow;
+module_param(low_rate_allow, bool, 0444);
+MODULE_PARM_DESC(low_rate_allow,
+ "Allow IMU rates below the minimum advisable when external clk is used in SCALED mode (default: N)");
+
#ifdef CONFIG_DEBUG_FS
static ssize_t adis16475_show_firmware_revision(struct file *file,
char __user *userbuf,
@@ -253,25 +261,92 @@ static int adis16475_get_freq(struct adis16475 *st, u32 *freq)
{
int ret;
u16 dec;
+ u32 sample_rate = st->clk_freq;
+
+ adis_dev_lock(&st->adis);
+
+ if (st->sync_mode == ADIS16475_SYNC_SCALED) {
+ u16 sync_scale;
+
+ ret = __adis_read_reg_16(&st->adis, ADIS16475_REG_UP_SCALE, &sync_scale);
+ if (ret)
+ goto error;
+
+ sample_rate = st->clk_freq * sync_scale;
+ }
- ret = adis_read_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, &dec);
+ ret = __adis_read_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, &dec);
if (ret)
- return -EINVAL;
+ goto error;
+
+ adis_dev_unlock(&st->adis);
- *freq = DIV_ROUND_CLOSEST(st->clk_freq, dec + 1);
+ *freq = DIV_ROUND_CLOSEST(sample_rate, dec + 1);
return 0;
+error:
+ adis_dev_unlock(&st->adis);
+ return ret;
}
static int adis16475_set_freq(struct adis16475 *st, const u32 freq)
{
u16 dec;
int ret;
+ u32 sample_rate = st->clk_freq;
if (!freq)
return -EINVAL;
- dec = DIV_ROUND_CLOSEST(st->clk_freq, freq);
+ adis_dev_lock(&st->adis);
+ /*
+ * When using sync scaled mode, the input clock needs to be scaled so that we have
+ * an IMU sample rate between (optimally) 1900 and 2100. After this, we can use the
+ * decimation filter to lower the sampling rate in order to get what the user wants.
+ * Optimally, the user sample rate is a multiple of both the IMU sample rate and
+ * the input clock. Hence, calculating the sync_scale dynamically gives us better
+ * chances of achieving a perfect/integer value for DEC_RATE. The math here is:
+ * 1. lcm of the input clock and the desired output rate.
+ * 2. get the highest multiple of the previous result lower than the adis max rate.
+ * 3. The last result becomes the IMU sample rate. Use that to calculate SYNC_SCALE
+ * and DEC_RATE (to get the user output rate)
+ */
+ if (st->sync_mode == ADIS16475_SYNC_SCALED) {
+ unsigned long scaled_rate = lcm(st->clk_freq, freq);
+ int sync_scale;
+
+ /*
+ * If lcm is bigger than the IMU maximum sampling rate there's no perfect
+ * solution. In this case, we get the highest multiple of the input clock
+ * lower than the IMU max sample rate.
+ */
+ if (scaled_rate > 2100000)
+ scaled_rate = 2100000 / st->clk_freq * st->clk_freq;
+ else
+ scaled_rate = 2100000 / scaled_rate * scaled_rate;
+
+ /*
+ * This is not an hard requirement but it's not advised to run the IMU
+ * with a sample rate lower than 4000Hz due to possible undersampling
+ * issues. However, there are users that might really want to take the risk.
+ * Hence, we provide a module parameter for them. If set, we allow sample
+ * rates lower than 4KHz. By default, we won't allow this and we just roundup
+ * the rate to the next multiple of the input clock bigger than 4KHz. This
+ * is done like this as in some cases (when DEC_RATE is 0) might give
+ * us the closest value to the one desired by the user...
+ */
+ if (scaled_rate < 1900000 && !low_rate_allow)
+ scaled_rate = roundup(1900000, st->clk_freq);
+
+ sync_scale = scaled_rate / st->clk_freq;
+ ret = __adis_write_reg_16(&st->adis, ADIS16475_REG_UP_SCALE, sync_scale);
+ if (ret)
+ goto error;
+
+ sample_rate = scaled_rate;
+ }
+
+ dec = DIV_ROUND_CLOSEST(sample_rate, freq);
if (dec)
dec--;
@@ -281,7 +356,7 @@ static int adis16475_set_freq(struct adis16475 *st, const u32 freq)
ret = adis_write_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, dec);
if (ret)
- return ret;
+ goto error;
/*
* If decimation is used, then gyro and accel data will have meaningful
@@ -290,6 +365,9 @@ static int adis16475_set_freq(struct adis16475 *st, const u32 freq)
assign_bit(ADIS16475_LSB_DEC_MASK, &st->lsb_flag, dec);
return 0;
+error:
+ adis_dev_unlock(&st->adis);
+ return ret;
}
/* The values are approximated. */
@@ -1085,6 +1163,7 @@ static int adis16475_config_sync_mode(struct adis16475 *st)
}
sync = &st->info->sync[sync_mode];
+ st->sync_mode = sync->sync_mode;
/* All the other modes require external input signal */
if (sync->sync_mode != ADIS16475_SYNC_OUTPUT) {
@@ -1112,37 +1191,20 @@ static int adis16475_config_sync_mode(struct adis16475 *st)
if (sync->sync_mode == ADIS16475_SYNC_SCALED) {
u16 up_scale;
- u32 scaled_out_freq = 0;
+
/*
- * If we are in scaled mode, we must have an up_scale.
- * In scaled mode the allowable input clock range is
- * 1 Hz to 128 Hz, and the allowable output range is
- * 1900 to 2100 Hz. Hence, a scale must be given to
- * get the allowable output.
+ * In sync scaled mode, the IMU sample rate is the clk_freq * sync_scale.
+ * Hence, default the IMU sample rate to the highest multiple of the input
+ * clock lower than the IMU max sample rate. The optimal range is
+ * 1900-2100 sps...
*/
- ret = device_property_read_u32(dev,
- "adi,scaled-output-hz",
- &scaled_out_freq);
- if (ret) {
- dev_err(dev, "adi,scaled-output-hz must be given when in scaled sync mode");
- return -EINVAL;
- } else if (scaled_out_freq < 1900 ||
- scaled_out_freq > 2100) {
- dev_err(dev, "Invalid value: %u for adi,scaled-output-hz",
- scaled_out_freq);
- return -EINVAL;
- }
-
- up_scale = DIV_ROUND_CLOSEST(scaled_out_freq,
- st->clk_freq);
+ up_scale = 2100 / st->clk_freq;
ret = __adis_write_reg_16(&st->adis,
ADIS16475_REG_UP_SCALE,
up_scale);
if (ret)
return ret;
-
- st->clk_freq = scaled_out_freq;
}
st->clk_freq *= 1000;
@@ -1196,6 +1258,9 @@ static int adis16475_config_irq_pin(struct adis16475 *st)
return -EINVAL;
}
+ /* We cannot mask the interrupt so ensure it's not enabled at request */
+ st->adis.irq_flag |= IRQF_NO_AUTOEN;
+
val = ADIS16475_MSG_CTRL_DR_POL(polarity);
ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
ADIS16475_MSG_CTRL_DR_POL_MASK, val);
@@ -1300,8 +1365,6 @@ static int adis16475_probe(struct spi_device *spi)
if (ret)
return ret;
- adis16475_enable_irq(&st->adis, false);
-
ret = devm_iio_device_register(&spi->dev, indio_dev);
if (ret)
return ret;
diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c
index dfe86c589325..f81b86690b76 100644
--- a/drivers/iio/imu/adis16480.c
+++ b/drivers/iio/imu/adis16480.c
@@ -10,6 +10,7 @@
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/math.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/kernel.h>
@@ -17,6 +18,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/module.h>
+#include <linux/lcm.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -170,6 +172,11 @@ static const char * const adis16480_int_pin_names[4] = {
[ADIS16480_PIN_DIO4] = "DIO4",
};
+static bool low_rate_allow;
+module_param(low_rate_allow, bool, 0444);
+MODULE_PARM_DESC(low_rate_allow,
+ "Allow IMU rates below the minimum advisable when external clk is used in PPS mode (default: N)");
+
#ifdef CONFIG_DEBUG_FS
static ssize_t adis16480_show_firmware_revision(struct file *file,
@@ -312,7 +319,8 @@ static int adis16480_debugfs_init(struct iio_dev *indio_dev)
static int adis16480_set_freq(struct iio_dev *indio_dev, int val, int val2)
{
struct adis16480 *st = iio_priv(indio_dev);
- unsigned int t, reg;
+ unsigned int t, sample_rate = st->clk_freq;
+ int ret;
if (val < 0 || val2 < 0)
return -EINVAL;
@@ -321,28 +329,65 @@ static int adis16480_set_freq(struct iio_dev *indio_dev, int val, int val2)
if (t == 0)
return -EINVAL;
+ adis_dev_lock(&st->adis);
/*
- * When using PPS mode, the rate of data collection is equal to the
- * product of the external clock frequency and the scale factor in the
- * SYNC_SCALE register.
- * When using sync mode, or internal clock, the output data rate is
- * equal with the clock frequency divided by DEC_RATE + 1.
+ * When using PPS mode, the input clock needs to be scaled so that we have an IMU
+ * sample rate between (optimally) 4000 and 4250. After this, we can use the
+ * decimation filter to lower the sampling rate in order to get what the user wants.
+ * Optimally, the user sample rate is a multiple of both the IMU sample rate and
+ * the input clock. Hence, calculating the sync_scale dynamically gives us better
+ * chances of achieving a perfect/integer value for DEC_RATE. The math here is:
+ * 1. lcm of the input clock and the desired output rate.
+ * 2. get the highest multiple of the previous result lower than the adis max rate.
+ * 3. The last result becomes the IMU sample rate. Use that to calculate SYNC_SCALE
+ * and DEC_RATE (to get the user output rate)
*/
if (st->clk_mode == ADIS16480_CLK_PPS) {
- t = t / st->clk_freq;
- reg = ADIS16495_REG_SYNC_SCALE;
- } else {
- t = st->clk_freq / t;
- reg = ADIS16480_REG_DEC_RATE;
+ unsigned long scaled_rate = lcm(st->clk_freq, t);
+ int sync_scale;
+
+ /*
+ * If lcm is bigger than the IMU maximum sampling rate there's no perfect
+ * solution. In this case, we get the highest multiple of the input clock
+ * lower than the IMU max sample rate.
+ */
+ if (scaled_rate > st->chip_info->int_clk)
+ scaled_rate = st->chip_info->int_clk / st->clk_freq * st->clk_freq;
+ else
+ scaled_rate = st->chip_info->int_clk / scaled_rate * scaled_rate;
+
+ /*
+ * This is not an hard requirement but it's not advised to run the IMU
+ * with a sample rate lower than 4000Hz due to possible undersampling
+ * issues. However, there are users that might really want to take the risk.
+ * Hence, we provide a module parameter for them. If set, we allow sample
+ * rates lower than 4KHz. By default, we won't allow this and we just roundup
+ * the rate to the next multiple of the input clock bigger than 4KHz. This
+ * is done like this as in some cases (when DEC_RATE is 0) might give
+ * us the closest value to the one desired by the user...
+ */
+ if (scaled_rate < 4000000 && !low_rate_allow)
+ scaled_rate = roundup(4000000, st->clk_freq);
+
+ sync_scale = scaled_rate / st->clk_freq;
+ ret = __adis_write_reg_16(&st->adis, ADIS16495_REG_SYNC_SCALE, sync_scale);
+ if (ret)
+ goto error;
+
+ sample_rate = scaled_rate;
}
+ t = DIV_ROUND_CLOSEST(sample_rate, t);
+ if (t)
+ t--;
+
if (t > st->chip_info->max_dec_rate)
t = st->chip_info->max_dec_rate;
- if ((t != 0) && (st->clk_mode != ADIS16480_CLK_PPS))
- t--;
-
- return adis_write_reg_16(&st->adis, reg, t);
+ ret = __adis_write_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, t);
+error:
+ adis_dev_unlock(&st->adis);
+ return ret;
}
static int adis16480_get_freq(struct iio_dev *indio_dev, int *val, int *val2)
@@ -350,34 +395,35 @@ static int adis16480_get_freq(struct iio_dev *indio_dev, int *val, int *val2)
struct adis16480 *st = iio_priv(indio_dev);
uint16_t t;
int ret;
- unsigned int freq;
- unsigned int reg;
+ unsigned int freq, sample_rate = st->clk_freq;
- if (st->clk_mode == ADIS16480_CLK_PPS)
- reg = ADIS16495_REG_SYNC_SCALE;
- else
- reg = ADIS16480_REG_DEC_RATE;
+ adis_dev_lock(&st->adis);
+
+ if (st->clk_mode == ADIS16480_CLK_PPS) {
+ u16 sync_scale;
+
+ ret = __adis_read_reg_16(&st->adis, ADIS16495_REG_SYNC_SCALE, &sync_scale);
+ if (ret)
+ goto error;
- ret = adis_read_reg_16(&st->adis, reg, &t);
+ sample_rate = st->clk_freq * sync_scale;
+ }
+
+ ret = __adis_read_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, &t);
if (ret)
- return ret;
+ goto error;
- /*
- * When using PPS mode, the rate of data collection is equal to the
- * product of the external clock frequency and the scale factor in the
- * SYNC_SCALE register.
- * When using sync mode, or internal clock, the output data rate is
- * equal with the clock frequency divided by DEC_RATE + 1.
- */
- if (st->clk_mode == ADIS16480_CLK_PPS)
- freq = st->clk_freq * t;
- else
- freq = st->clk_freq / (t + 1);
+ adis_dev_unlock(&st->adis);
+
+ freq = DIV_ROUND_CLOSEST(sample_rate, (t + 1));
*val = freq / 1000;
*val2 = (freq % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO;
+error:
+ adis_dev_unlock(&st->adis);
+ return ret;
}
enum {
@@ -552,7 +598,6 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, unsigned int freq)
{
struct adis16480 *st = iio_priv(indio_dev);
- struct mutex *slock = &st->adis.state_lock;
unsigned int enable_mask, offset, reg;
unsigned int diff, best_diff;
unsigned int i, best_freq;
@@ -563,7 +608,7 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev,
offset = ad16480_filter_data[chan->scan_index][1];
enable_mask = BIT(offset + 2);
- mutex_lock(slock);
+ adis_dev_lock(&st->adis);
ret = __adis_read_reg_16(&st->adis, reg, &val);
if (ret)
@@ -591,7 +636,7 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev,
ret = __adis_write_reg_16(&st->adis, reg, val);
out_unlock:
- mutex_unlock(slock);
+ adis_dev_unlock(&st->adis);
return ret;
}
@@ -1278,6 +1323,20 @@ static int adis16480_probe(struct spi_device *spi)
st->clk_freq = clk_get_rate(st->ext_clk);
st->clk_freq *= 1000; /* micro */
+ if (st->clk_mode == ADIS16480_CLK_PPS) {
+ u16 sync_scale;
+
+ /*
+ * In PPS mode, the IMU sample rate is the clk_freq * sync_scale. Hence,
+ * default the IMU sample rate to the highest multiple of the input clock
+ * lower than the IMU max sample rate. The internal sample rate is the
+ * max...
+ */
+ sync_scale = st->chip_info->int_clk / st->clk_freq;
+ ret = __adis_write_reg_16(&st->adis, ADIS16495_REG_SYNC_SCALE, sync_scale);
+ if (ret)
+ return ret;
+ }
} else {
st->clk_freq = st->chip_info->int_clk;
}
diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
index 64e0ba51cb18..fa5540fabacc 100644
--- a/drivers/iio/imu/adis_trigger.c
+++ b/drivers/iio/imu/adis_trigger.c
@@ -27,27 +27,21 @@ static const struct iio_trigger_ops adis_trigger_ops = {
.set_trigger_state = &adis_data_rdy_trigger_set_state,
};
-static void adis_trigger_setup(struct adis *adis)
-{
- adis->trig->dev.parent = &adis->spi->dev;
- adis->trig->ops = &adis_trigger_ops;
- iio_trigger_set_drvdata(adis->trig, adis);
-}
-
static int adis_validate_irq_flag(struct adis *adis)
{
+ unsigned long direction = adis->irq_flag & IRQF_TRIGGER_MASK;
/*
* Typically this devices have data ready either on the rising edge or
* on the falling edge of the data ready pin. This checks enforces that
* one of those is set in the drivers... It defaults to
- * IRQF_TRIGGER_RISING for backward compatibility wiht devices that
+ * IRQF_TRIGGER_RISING for backward compatibility with devices that
* don't support changing the pin polarity.
*/
- if (!adis->irq_flag) {
- adis->irq_flag = IRQF_TRIGGER_RISING;
+ if (direction == IRQF_TRIGGER_NONE) {
+ adis->irq_flag |= IRQF_TRIGGER_RISING;
return 0;
- } else if (adis->irq_flag != IRQF_TRIGGER_RISING &&
- adis->irq_flag != IRQF_TRIGGER_FALLING) {
+ } else if (direction != IRQF_TRIGGER_RISING &&
+ direction != IRQF_TRIGGER_FALLING) {
dev_err(&adis->spi->dev, "Invalid IRQ mask: %08lx\n",
adis->irq_flag);
return -EINVAL;
@@ -72,7 +66,8 @@ int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
if (!adis->trig)
return -ENOMEM;
- adis_trigger_setup(adis);
+ adis->trig->ops = &adis_trigger_ops;
+ iio_trigger_set_drvdata(adis->trig, adis);
ret = adis_validate_irq_flag(adis);
if (ret)
diff --git a/drivers/iio/imu/fxos8700_i2c.c b/drivers/iio/imu/fxos8700_i2c.c
index 3ceb76366313..40a570325b0a 100644
--- a/drivers/iio/imu/fxos8700_i2c.c
+++ b/drivers/iio/imu/fxos8700_i2c.c
@@ -26,8 +26,7 @@ static int fxos8700_i2c_probe(struct i2c_client *client,
regmap = devm_regmap_init_i2c(client, &fxos8700_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&client->dev, "Failed to register i2c regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&client->dev, "Failed to register i2c regmap %ld\n", PTR_ERR(regmap));
return PTR_ERR(regmap);
}
diff --git a/drivers/iio/imu/fxos8700_spi.c b/drivers/iio/imu/fxos8700_spi.c
index 57e7bb6444e7..27e694cce173 100644
--- a/drivers/iio/imu/fxos8700_spi.c
+++ b/drivers/iio/imu/fxos8700_spi.c
@@ -17,8 +17,7 @@ static int fxos8700_spi_probe(struct spi_device *spi)
regmap = devm_regmap_init_spi(spi, &fxos8700_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&spi->dev, "Failed to register spi regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&spi->dev, "Failed to register spi regmap %ld\n", PTR_ERR(regmap));
return PTR_ERR(regmap);
}
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 3441b0d61c5d..383cc3250342 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -709,7 +709,6 @@ struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st)
const char *name;
struct inv_icm42600_timestamp *ts;
struct iio_dev *indio_dev;
- struct iio_buffer *buffer;
int ret;
name = devm_kasprintf(dev, GFP_KERNEL, "%s-accel", st->name);
@@ -720,23 +719,22 @@ struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st)
if (!indio_dev)
return ERR_PTR(-ENOMEM);
- buffer = devm_iio_kfifo_allocate(dev);
- if (!buffer)
- return ERR_PTR(-ENOMEM);
-
ts = iio_priv(indio_dev);
inv_icm42600_timestamp_init(ts, inv_icm42600_odr_to_period(st->conf.accel.odr));
iio_device_set_drvdata(indio_dev, st);
indio_dev->name = name;
indio_dev->info = &inv_icm42600_accel_info;
- indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
+ indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = inv_icm42600_accel_channels;
indio_dev->num_channels = ARRAY_SIZE(inv_icm42600_accel_channels);
indio_dev->available_scan_masks = inv_icm42600_accel_scan_masks;
- indio_dev->setup_ops = &inv_icm42600_buffer_ops;
- iio_device_attach_buffer(indio_dev, buffer);
+ ret = devm_iio_kfifo_buffer_setup(dev, indio_dev,
+ INDIO_BUFFER_SOFTWARE,
+ &inv_icm42600_buffer_ops);
+ if (ret)
+ return ERR_PTR(ret);
ret = devm_iio_device_register(dev, indio_dev);
if (ret)
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
index aee7b9ff4bf4..cec1dd0e0464 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
@@ -720,7 +720,6 @@ struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st)
const char *name;
struct inv_icm42600_timestamp *ts;
struct iio_dev *indio_dev;
- struct iio_buffer *buffer;
int ret;
name = devm_kasprintf(dev, GFP_KERNEL, "%s-gyro", st->name);
@@ -731,23 +730,23 @@ struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st)
if (!indio_dev)
return ERR_PTR(-ENOMEM);
- buffer = devm_iio_kfifo_allocate(dev);
- if (!buffer)
- return ERR_PTR(-ENOMEM);
-
ts = iio_priv(indio_dev);
inv_icm42600_timestamp_init(ts, inv_icm42600_odr_to_period(st->conf.gyro.odr));
iio_device_set_drvdata(indio_dev, st);
indio_dev->name = name;
indio_dev->info = &inv_icm42600_gyro_info;
- indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
+ indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = inv_icm42600_gyro_channels;
indio_dev->num_channels = ARRAY_SIZE(inv_icm42600_gyro_channels);
indio_dev->available_scan_masks = inv_icm42600_gyro_scan_masks;
indio_dev->setup_ops = &inv_icm42600_buffer_ops;
- iio_device_attach_buffer(indio_dev, buffer);
+ ret = devm_iio_kfifo_buffer_setup(dev, indio_dev,
+ INDIO_BUFFER_SOFTWARE,
+ &inv_icm42600_buffer_ops);
+ if (ret)
+ return ERR_PTR(ret);
ret = devm_iio_device_register(dev, indio_dev);
if (ret)
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 453c51c79655..6244a07048df 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -731,12 +731,16 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
}
}
-static int inv_mpu6050_write_gyro_scale(struct inv_mpu6050_state *st, int val)
+static int inv_mpu6050_write_gyro_scale(struct inv_mpu6050_state *st, int val,
+ int val2)
{
int result, i;
+ if (val != 0)
+ return -EINVAL;
+
for (i = 0; i < ARRAY_SIZE(gyro_scale_6050); ++i) {
- if (gyro_scale_6050[i] == val) {
+ if (gyro_scale_6050[i] == val2) {
result = inv_mpu6050_set_gyro_fsr(st, i);
if (result)
return result;
@@ -767,13 +771,17 @@ static int inv_write_raw_get_fmt(struct iio_dev *indio_dev,
return -EINVAL;
}
-static int inv_mpu6050_write_accel_scale(struct inv_mpu6050_state *st, int val)
+static int inv_mpu6050_write_accel_scale(struct inv_mpu6050_state *st, int val,
+ int val2)
{
int result, i;
u8 d;
+ if (val != 0)
+ return -EINVAL;
+
for (i = 0; i < ARRAY_SIZE(accel_scale); ++i) {
- if (accel_scale[i] == val) {
+ if (accel_scale[i] == val2) {
d = (i << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
result = regmap_write(st->map, st->reg->accl_config, d);
if (result)
@@ -814,10 +822,10 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_ANGL_VEL:
- result = inv_mpu6050_write_gyro_scale(st, val2);
+ result = inv_mpu6050_write_gyro_scale(st, val, val2);
break;
case IIO_ACCEL:
- result = inv_mpu6050_write_accel_scale(st, val2);
+ result = inv_mpu6050_write_accel_scale(st, val, val2);
break;
default:
result = -EINVAL;
@@ -1458,15 +1466,21 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
st->plat_data = *pdata;
}
- desc = irq_get_irq_data(irq);
- if (!desc) {
- dev_err(dev, "Could not find IRQ %d\n", irq);
- return -EINVAL;
- }
+ if (irq > 0) {
+ desc = irq_get_irq_data(irq);
+ if (!desc) {
+ dev_err(dev, "Could not find IRQ %d\n", irq);
+ return -EINVAL;
+ }
- irq_type = irqd_get_trigger_type(desc);
- if (!irq_type)
+ irq_type = irqd_get_trigger_type(desc);
+ if (!irq_type)
+ irq_type = IRQF_TRIGGER_RISING;
+ } else {
+ /* Doesn't really matter, use the default */
irq_type = IRQF_TRIGGER_RISING;
+ }
+
if (irq_type & IRQF_TRIGGER_RISING) // rising or both-edge
st->irq_mask = INV_MPU6050_ACTIVE_HIGH;
else if (irq_type == IRQF_TRIGGER_FALLING)
@@ -1591,20 +1605,26 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
}
indio_dev->info = &mpu_info;
- indio_dev->modes = INDIO_BUFFER_TRIGGERED;
- result = devm_iio_triggered_buffer_setup(dev, indio_dev,
- iio_pollfunc_store_time,
- inv_mpu6050_read_fifo,
- NULL);
- if (result) {
- dev_err(dev, "configure buffer fail %d\n", result);
- return result;
- }
- result = inv_mpu6050_probe_trigger(indio_dev, irq_type);
- if (result) {
- dev_err(dev, "trigger probe fail %d\n", result);
- return result;
+ if (irq > 0) {
+ /*
+ * The driver currently only supports buffered capture with its
+ * own trigger. So no IRQ, no trigger, no buffer
+ */
+ result = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ inv_mpu6050_read_fifo,
+ NULL);
+ if (result) {
+ dev_err(dev, "configure buffer fail %d\n", result);
+ return result;
+ }
+
+ result = inv_mpu6050_probe_trigger(indio_dev, irq_type);
+ if (result) {
+ dev_err(dev, "trigger probe fail %d\n", result);
+ return result;
+ }
}
result = devm_iio_device_register(dev, indio_dev);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
index f7b5a70be30f..de8ed1446d60 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
@@ -11,6 +11,16 @@ static unsigned int inv_scan_query_mpu6050(struct iio_dev *indio_dev)
struct inv_mpu6050_state *st = iio_priv(indio_dev);
unsigned int mask;
+ /*
+ * If the MPU6050 is just used as a trigger, then the scan mask
+ * is not allocated so we simply enable the temperature channel
+ * as a dummy and bail out.
+ */
+ if (!indio_dev->active_scan_mask) {
+ st->chip_config.temp_fifo_enable = true;
+ return INV_MPU6050_SENSOR_TEMP;
+ }
+
st->chip_config.gyro_fifo_enable =
test_bit(INV_MPU6050_SCAN_GYRO_X,
indio_dev->active_scan_mask) ||
diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c
index 4377047d503a..fc5a60fcfec0 100644
--- a/drivers/iio/imu/kmx61.c
+++ b/drivers/iio/imu/kmx61.c
@@ -1268,7 +1268,6 @@ static struct iio_trigger *kmx61_trigger_setup(struct kmx61_data *data,
if (!trig)
return ERR_PTR(-ENOMEM);
- trig->dev.parent = &data->client->dev;
trig->ops = &kmx61_trigger_ops;
iio_trigger_set_drvdata(trig, indio_dev);
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
index f1103ecedd64..16730a780964 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
@@ -739,20 +739,17 @@ static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = {
int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
{
- struct iio_buffer *buffer;
- int i;
+ int i, ret;
for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
if (!hw->iio_devs[i])
continue;
- buffer = devm_iio_kfifo_allocate(hw->dev);
- if (!buffer)
- return -ENOMEM;
-
- iio_device_attach_buffer(hw->iio_devs[i], buffer);
- hw->iio_devs[i]->modes |= INDIO_BUFFER_SOFTWARE;
- hw->iio_devs[i]->setup_ops = &st_lsm6dsx_buffer_ops;
+ ret = devm_iio_kfifo_buffer_setup(hw->dev, hw->iio_devs[i],
+ INDIO_BUFFER_SOFTWARE,
+ &st_lsm6dsx_buffer_ops);
+ if (ret)
+ return ret;
}
return 0;
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
index ec8d4351390a..8b4fc2c15622 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
@@ -29,8 +29,7 @@ static int st_lsm6dsx_i2c_probe(struct i2c_client *client,
regmap = devm_regmap_init_i2c(client, &st_lsm6dsx_i2c_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&client->dev, "Failed to register i2c regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&client->dev, "Failed to register i2c regmap %ld\n", PTR_ERR(regmap));
return PTR_ERR(regmap);
}
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c
index 57e633121bdc..8d4201b86e87 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c
@@ -34,8 +34,7 @@ static int st_lsm6dsx_i3c_probe(struct i3c_device *i3cdev)
regmap = devm_regmap_init_i3c(i3cdev, &st_lsm6dsx_i3c_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&i3cdev->dev, "Failed to register i3c regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&i3cdev->dev, "Failed to register i3c regmap %ld\n", PTR_ERR(regmap));
return PTR_ERR(regmap);
}
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
index 349ec9c1890d..e80110b6b280 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
@@ -29,8 +29,7 @@ static int st_lsm6dsx_spi_probe(struct spi_device *spi)
regmap = devm_regmap_init_spi(spi, &st_lsm6dsx_spi_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&spi->dev, "Failed to register spi regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&spi->dev, "Failed to register spi regmap %ld\n", PTR_ERR(regmap));
return PTR_ERR(regmap);
}