summaryrefslogtreecommitdiff
path: root/drivers/iio/imu/adis.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-01-10 12:44:00 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-01-10 12:44:00 +0300
commit821f7ce79fd1ef2bf96a1b93521d8800abd24a1f (patch)
treed17f9fd1ade5c3e0a70a1ab8ae04964b1290dcf5 /drivers/iio/imu/adis.c
parent0469fc6a1a8715b5c09117a26700da0d67061fb5 (diff)
parentc1d1c4a62db5c4745b9e15cfee0daf0f774f73fc (diff)
downloadlinux-821f7ce79fd1ef2bf96a1b93521d8800abd24a1f.tar.xz
Merge tag 'iio-for-5.6a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes: First set of new device support, features and cleanups for IIO in the 5.6 cycle New device support * ad7091r5 ADC - New driver with follow up patch adding scale and vref support. - DT bindings * ad7923 - Support for ad7908, ad7918 and ad7928 added to driver. * bma180 - Support the BMA254 accelerometer. Required fairly substantial rework to allow for small differences between this an existing parts. * bma400 accelerometer - New driver with follow up patch for regulator support. - DT bindings. * asc dlhl60d - New driver support this range of pressure and temperature sensors. - DT bindings. * ltc2496 ADC - New driver to support this ADC. - Split the existing LTC2497 driver generic component out and reuse. - DT bindings. * parallax ping - New driver supporting ultrasonic and laser tof distance sensors. - Bindings for these sensors. New features * core - New char type for read_raw returns, used for thermocouple types. - Rename read_first_n callback to read. The reasons behind the original naming are lost to the mists of time. * ad799x - Allow pm_ops to disable device completely allowing regulator power down. * bma180 - Enable basic regulator support. * dmaengine buffer - Report platform data alignment requirements via new ABI. * max31856 - Add option to set mains filter rejection frequency and document new in_temp_filter_notch_center_frequency ABI. - Add support for configuring HW averaging (oversampling ratio) - Add runtime configuration of thermocouple type and document new ABI. * maxim-thermocouple - Add read only access to thermocouple type using new ABI, includes adding more specific compatibles to reflect which variant of the chip is being used. * mpu6050 - Provide option to support the PMU9150 in package magnetometer directly rather than via auxiliary bus. * stm32_adc - Add overrun interrupt checks to detect if this happens. * st_lsm6dsx - Enable the sensor-hub support for lsm6dsm. Includes various reworks to allow this. Cleanups and minor fixes * Subsystem wide - Tidy up indentation in Kconfig and fix alphabetical order of AD7091R5. - Drop linux/gpio.h and linux/of_gpio.h from drivers that don't use them. * ad7266 - Convert to GPIO descriptors. * ad7303 - Avoid a dance with checking if the regulator is supplied by just using the optional request interface. * ad7887 - Simplify channel specification assignment to enable adding more devices. * ad7923 - Drop some unused and largely pointless defines of BOB_N==N variety. - Tidy up checkpatch warnings. - Add missing of_device_id table. * adf4350 - Convert to GPIO descriptors. * ak8975 - Convert to GPIO descriptors. * ADIS library and drivers - Expand scope of txrx_lock to cover all state and rename as state_lock - Add unlocked read / write to allow grouping of consecutive calls under single lock / unlock. - Add unlocked check_status, reset to allow grouping under single lock / unlock. - Remove remaining uses of core mlock for local state protection. mlock should never be used directly as it protects tightly defined core IIO device management state. * adis16240 - Enforce only supported SPI mode on driver load + add DT binding doc. * atlas-ph-sensor - Rename to atlas-sensor given it now covers things beyond ph sensors. * bma180 - Use local dev variable to tidy up code. - Use c99 style explicity .member assignment to make driver more readable. * bmp280 - Drop ACPI support. No evidence this was used and appropriate ID is not registered. - Allow ACPI to bind device via PRP0001 * dmaengine buffer - Use dma_request_chan instead of dma_request_slave_channel_reason as that ABI is going away. - Add module info to avoid tainting the kernel. * hts221 - Avoid magic number defines when only used to fill structure elements that are self describing. * lm3533 - Drop a stray semicolon. * max9611 - Cleanup enum handling to be more resilient to future changes. * mpu6050 - Delete MPU9150 from supported SPI devices as doesn't provide SPI. - Select I2C_MUX again after kbuild issue fixed elsewhere. * stm32-timer - Drop an unnecessary register update. * ssp_sensors - Convert to GPIO descriptors. * st_sensors - drop !CONFIG_ACPI defines as ACPI_PTR() will stop them being used anyway. - Make default platform data structures __maybe_unsued. - Fill in some missing kernel-doc function parameters. * st_lsm6dsx - white space fixes. - Mark some constants that aren't always used as __maybe_unused. - Drop of ID table guards as they just pervent use under ACPI. - Switch to device properties to allow ACPI usage. * st_uvis25 - Drop acpi.h include as no ACPI APIs used. * ti-ads1015 - Drop legacy platform data as no one seems to be using it. - Use the device property API instead of OF specific. * ti-ads7950 - typo fix in error message. * tag 'iio-for-5.6a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (99 commits) iio: accel: bma180: BMA254 support iio: pressure: bmp280: Allow device to be enumerated from ACPI iio: pressure: bmp280: Drop ACPI support dt-bindings: iio: adc: convert sd modulator to json-schema iio: buffer: rename 'read_first_n' callback to 'read' iio: buffer-dmaengine: Report buffer length requirements bindings: iio: pressure: Add documentation for dlh driver dt-bindings: Add asc vendor iio: pressure: Add driver for DLH pressure sensors iio: buffer-dmaengine: Add module information iio: accel: bma180: Use explicit member assignment iio: accel: bma180: Basic regulator support iio: accel: bma180: Add dev helper variable iio: imu: st_lsm6dsx: enable sensor-hub support for lsm6dsm iio: imu: st_lsm6dsx: rename st_lsm6dsx_shub_read_reg in st_lsm6dsx_shub_read_output iio: imu: st_lsm6dsx: check if shub_output reg is located in primary page iio: imu: st_lsm6dsx: check if pull_up is located in primary page iio: imu: st_lsm6dsx: check if master_enable is located in primary page iio: imu: st_lsm6dsx: export max num of slave devices in st_lsm6dsx_shub_settings iio: light: remove unneeded semicolon ...
Diffstat (limited to 'drivers/iio/imu/adis.c')
-rw-r--r--drivers/iio/imu/adis.c94
1 files changed, 50 insertions, 44 deletions
diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c
index e14c8536fd09..9ba4a7c8e7ad 100644
--- a/drivers/iio/imu/adis.c
+++ b/drivers/iio/imu/adis.c
@@ -26,7 +26,14 @@
#define ADIS_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
#define ADIS_GLOB_CMD_SW_RESET BIT(7)
-int adis_write_reg(struct adis *adis, unsigned int reg,
+/**
+ * __adis_write_reg() - write N bytes to register (unlocked version)
+ * @adis: The adis device
+ * @reg: The address of the lower of the two registers
+ * @value: The value to write to device (up to 4 bytes)
+ * @size: The size of the @value (in bytes)
+ */
+int __adis_write_reg(struct adis *adis, unsigned int reg,
unsigned int value, unsigned int size)
{
unsigned int page = reg / ADIS_PAGE_SIZE;
@@ -70,8 +77,6 @@ int adis_write_reg(struct adis *adis, unsigned int reg,
},
};
- mutex_lock(&adis->txrx_lock);
-
spi_message_init(&msg);
if (adis->current_page != page) {
@@ -96,8 +101,7 @@ int adis_write_reg(struct adis *adis, unsigned int reg,
adis->tx[3] = value & 0xff;
break;
default:
- ret = -EINVAL;
- goto out_unlock;
+ return -EINVAL;
}
xfers[size].cs_change = 0;
@@ -113,20 +117,18 @@ int adis_write_reg(struct adis *adis, unsigned int reg,
adis->current_page = page;
}
-out_unlock:
- mutex_unlock(&adis->txrx_lock);
-
return ret;
}
-EXPORT_SYMBOL_GPL(adis_write_reg);
+EXPORT_SYMBOL_GPL(__adis_write_reg);
/**
- * adis_read_reg() - read 2 bytes from a 16-bit register
+ * __adis_read_reg() - read N bytes from register (unlocked version)
* @adis: The adis device
* @reg: The address of the lower of the two registers
* @val: The value read back from the device
+ * @size: The size of the @val buffer
*/
-int adis_read_reg(struct adis *adis, unsigned int reg,
+int __adis_read_reg(struct adis *adis, unsigned int reg,
unsigned int *val, unsigned int size)
{
unsigned int page = reg / ADIS_PAGE_SIZE;
@@ -166,7 +168,6 @@ int adis_read_reg(struct adis *adis, unsigned int reg,
},
};
- mutex_lock(&adis->txrx_lock);
spi_message_init(&msg);
if (adis->current_page != page) {
@@ -188,15 +189,14 @@ int adis_read_reg(struct adis *adis, unsigned int reg,
spi_message_add_tail(&xfers[3], &msg);
break;
default:
- ret = -EINVAL;
- goto out_unlock;
+ return -EINVAL;
}
ret = spi_sync(adis->spi, &msg);
if (ret) {
dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n",
reg, ret);
- goto out_unlock;
+ return ret;
} else {
adis->current_page = page;
}
@@ -210,12 +210,9 @@ int adis_read_reg(struct adis *adis, unsigned int reg,
break;
}
-out_unlock:
- mutex_unlock(&adis->txrx_lock);
-
return ret;
}
-EXPORT_SYMBOL_GPL(adis_read_reg);
+EXPORT_SYMBOL_GPL(__adis_read_reg);
#ifdef CONFIG_DEBUG_FS
@@ -253,12 +250,16 @@ int adis_enable_irq(struct adis *adis, bool enable)
int ret = 0;
uint16_t msc;
- if (adis->data->enable_irq)
- return adis->data->enable_irq(adis, enable);
+ mutex_lock(&adis->state_lock);
+
+ if (adis->data->enable_irq) {
+ ret = adis->data->enable_irq(adis, enable);
+ goto out_unlock;
+ }
- ret = adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc);
+ ret = __adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc);
if (ret)
- goto error_ret;
+ goto out_unlock;
msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH;
msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2;
@@ -267,26 +268,27 @@ int adis_enable_irq(struct adis *adis, bool enable)
else
msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN;
- ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc);
+ ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc);
-error_ret:
+out_unlock:
+ mutex_unlock(&adis->state_lock);
return ret;
}
EXPORT_SYMBOL(adis_enable_irq);
/**
- * adis_check_status() - Check the device for error conditions
+ * __adis_check_status() - Check the device for error conditions (unlocked)
* @adis: The adis device
*
* Returns 0 on success, a negative error code otherwise
*/
-int adis_check_status(struct adis *adis)
+int __adis_check_status(struct adis *adis)
{
uint16_t status;
int ret;
int i;
- ret = adis_read_reg_16(adis, adis->data->diag_stat_reg, &status);
+ ret = __adis_read_reg_16(adis, adis->data->diag_stat_reg, &status);
if (ret)
return ret;
@@ -304,32 +306,32 @@ int adis_check_status(struct adis *adis)
return -EIO;
}
-EXPORT_SYMBOL_GPL(adis_check_status);
+EXPORT_SYMBOL_GPL(__adis_check_status);
/**
- * adis_reset() - Reset the device
+ * __adis_reset() - Reset the device (unlocked version)
* @adis: The adis device
*
* Returns 0 on success, a negative error code otherwise
*/
-int adis_reset(struct adis *adis)
+int __adis_reset(struct adis *adis)
{
int ret;
- ret = adis_write_reg_8(adis, adis->data->glob_cmd_reg,
+ ret = __adis_write_reg_8(adis, adis->data->glob_cmd_reg,
ADIS_GLOB_CMD_SW_RESET);
if (ret)
dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret);
return ret;
}
-EXPORT_SYMBOL_GPL(adis_reset);
+EXPORT_SYMBOL_GPL(__adis_reset);
static int adis_self_test(struct adis *adis)
{
int ret;
- ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg,
+ ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg,
adis->data->self_test_mask);
if (ret) {
dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n",
@@ -339,10 +341,10 @@ static int adis_self_test(struct adis *adis)
msleep(adis->data->startup_delay);
- ret = adis_check_status(adis);
+ ret = __adis_check_status(adis);
if (adis->data->self_test_no_autoclear)
- adis_write_reg_16(adis, adis->data->msc_ctrl_reg, 0x00);
+ __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, 0x00);
return ret;
}
@@ -360,19 +362,23 @@ int adis_initial_startup(struct adis *adis)
{
int ret;
+ mutex_lock(&adis->state_lock);
+
ret = adis_self_test(adis);
if (ret) {
dev_err(&adis->spi->dev, "Self-test failed, trying reset.\n");
- adis_reset(adis);
+ __adis_reset(adis);
msleep(adis->data->startup_delay);
ret = adis_self_test(adis);
if (ret) {
dev_err(&adis->spi->dev, "Second self-test failed, giving up.\n");
- return ret;
+ goto out_unlock;
}
}
- return 0;
+out_unlock:
+ mutex_unlock(&adis->state_lock);
+ return ret;
}
EXPORT_SYMBOL_GPL(adis_initial_startup);
@@ -398,15 +404,15 @@ int adis_single_conversion(struct iio_dev *indio_dev,
unsigned int uval;
int ret;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&adis->state_lock);
- ret = adis_read_reg(adis, chan->address, &uval,
+ ret = __adis_read_reg(adis, chan->address, &uval,
chan->scan_type.storagebits / 8);
if (ret)
goto err_unlock;
if (uval & error_mask) {
- ret = adis_check_status(adis);
+ ret = __adis_check_status(adis);
if (ret)
goto err_unlock;
}
@@ -418,7 +424,7 @@ int adis_single_conversion(struct iio_dev *indio_dev,
ret = IIO_VAL_INT;
err_unlock:
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&adis->state_lock);
return ret;
}
EXPORT_SYMBOL_GPL(adis_single_conversion);
@@ -438,7 +444,7 @@ EXPORT_SYMBOL_GPL(adis_single_conversion);
int adis_init(struct adis *adis, struct iio_dev *indio_dev,
struct spi_device *spi, const struct adis_data *data)
{
- mutex_init(&adis->txrx_lock);
+ mutex_init(&adis->state_lock);
adis->spi = spi;
adis->data = data;
iio_device_set_drvdata(indio_dev, adis);