Commit eb7bfed9 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-4.7a' of...

Merge tag 'iio-for-4.7a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next

Jonathan writes:

First round of IIO new device support, features and cleanups for the 4.7 cycle.

New core support
* UV light modifier (for intensity)
* UV light index channel type.

New device support
* hp206c barometer and altimeter
  - new driver.
* mcp4131 potentiometer
  - new driver supporting lots of parts from Microchip.
* mma8452
  - FXLS8471Q support
- NXP LPC18XX SOC ADC
  - new driver.
- NXP LPC18XX SOC DAC
  - new driver.
- rockchip_saradc
  - support rk3399
* st accel
  - h3lis331dl support

Staging driver removals
* adis16204
  - obsolete part making it hard to get parts to test the driver in order
    to clean it up.
* adis16220
  - obsolete part making it hard to get the parts test the driver in order
    to clean it up.

Features
* core
  - convenience functions to claim / release direct access to the device.
    Makes more consistent handling of this corner easier. Used in ad7192 driver.
* ak8975
  - power regulator support.
* at91-sama5d2
  - differential channel support.
* mma8452
  - runtime pm support
  - drop device specific autosleep and use the runtime pm one instead.
* ms5611
  - DT bindings
  - oversampling ratio support

Cleanups and minor fixes
* MAINTAINERS
  - Peter got married - hence name change!

* Documentation
  - Fix a typo in in_proximity_raw description.
  - Add some missing docs for iio_buffer_access_funcs.

* Tools
  - update iio_event_monitor names to match new stuff.
  - make generic_buffer look for triggers ending in -trigger as we let these in
  for a number of drivers a long time back and now it is a fairly common
  option.

Drivers
* staging wide
  - convert bare unsigned usage to unsigned int to comply with coding style.
* non staging wide:
  - since boiler plate gpio handling of interrupts has been moved into the
   ACPI core we don't need to include gpio/consumer.h in a load of drivers so
   drop it.
* ad7606
  - fix an endian casting sparse warning.
* ak8975
  - fix a possible unitialized warning from gcc.
  - drop and unused field left over from earlier cleanups
  - fix a missing regulator_disable on exit.
* at91-sama5d2
  - typo and indentation
  - missing IOMEM dependency.
  - cleanup mode register usage by avoidling erasing whole thing when changing
  the sampling frequency.
* bmc150
  - use the core demux and available_scan_masks to simplify buffer handling
  - optimize the transfers in the trigger handler now we have a magic function
  to emulate bulk reads (under circumstances met here).  This matters with some
  rather dumb i2c adapters in particular.
  - use a single regmap_conf for all bus types as they were all the same.
* bmg160
  - use the core demux and available_scan_masks to simplify the buffer handling
  - optimize the transfers in the trigger handler now we have a magic funciton
  to emulate bulk rads (under circumstances met here).
  - drop gpio interrupt probing from the driver (ACPI) as now handled by the
  ACPI core.
* ina2xx-adc
  - update the CALIB register when RShunt changes.
  - fix scale for VShunt - in reality this error canceled out when used.
* isl29028
  - use regmap to retrieve the struct device instead of carrying a second
  copy of it around.
* kxcjk-1013
  - use core demux
  - optimize i2c transfers in the trigger handler.
* mcp4531
  - refactor to use a pointer to access model parameters instead of indexing
    into the array each time.
* mma8452
  - style fixes
  - avoid swtiching to active whenever the config changes
  - add missin i2c_device_id for mma8451
* mpu6050
  - fix possible NULL dereference.
  - fix the name / chip_id used when ACPI used (otherwise reports as NULL).
* ms5611
  - fix a missing regulator_disable that left the regulator on during removal.
* mxc4005
  - drop gpio interrupt handling for ACPI case from driver as the core now
  handles this case.
* st-sensors
  - note that there are only ever a maximum of 3 axis on current st-sensors
  so just allocate a fixed sized buffer big enough for that.
* tpl0102
  - change the i2c_check_functionality condition to bring it inline with other
    IIO users as EOPNOTSUPP.
* tsl2563
  - replace deprecated flush_scheduled_work
parents 56d118c2 486294f1
...@@ -1233,7 +1233,7 @@ KernelVersion: 3.4 ...@@ -1233,7 +1233,7 @@ KernelVersion: 3.4
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
Proximity measurement indicating that some Proximity measurement indicating that some
object is near the sensor, usually be observing object is near the sensor, usually by observing
reflectivity of infrared or ultrasound emitted. reflectivity of infrared or ultrasound emitted.
Often these sensors are unit less and as such conversion Often these sensors are unit less and as such conversion
to SI units is not possible. Higher proximity measurements to SI units is not possible. Higher proximity measurements
...@@ -1255,12 +1255,23 @@ Description: ...@@ -1255,12 +1255,23 @@ Description:
What: /sys/.../iio:deviceX/in_intensityY_raw What: /sys/.../iio:deviceX/in_intensityY_raw
What: /sys/.../iio:deviceX/in_intensityY_ir_raw What: /sys/.../iio:deviceX/in_intensityY_ir_raw
What: /sys/.../iio:deviceX/in_intensityY_both_raw What: /sys/.../iio:deviceX/in_intensityY_both_raw
What: /sys/.../iio:deviceX/in_intensityY_uv_raw
KernelVersion: 3.4 KernelVersion: 3.4
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
Unit-less light intensity. Modifiers both and ir indicate Unit-less light intensity. Modifiers both and ir indicate
that measurements contains visible and infrared light that measurements contains visible and infrared light
components or just infrared light, respectively. components or just infrared light, respectively. Modifier uv indicates
that measurements contain ultraviolet light components.
What: /sys/.../iio:deviceX/in_uvindex_input
KernelVersion: 4.6
Contact: linux-iio@vger.kernel.org
Description:
UV light intensity index measuring the human skin's response to
different wavelength of sunlight weighted according to the
standardised CIE Erythemal Action Spectrum. UV index values range
from 0 (low) to >=11 (extreme).
What: /sys/.../iio:deviceX/in_intensity_red_integration_time What: /sys/.../iio:deviceX/in_intensity_red_integration_time
What: /sys/.../iio:deviceX/in_intensity_green_integration_time What: /sys/.../iio:deviceX/in_intensity_green_integration_time
......
Freescale MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC or MMA8653FC Freescale MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC or FXLS8471Q
triaxial accelerometer triaxial accelerometer
Required properties: Required properties:
...@@ -9,6 +9,7 @@ Required properties: ...@@ -9,6 +9,7 @@ Required properties:
* "fsl,mma8453" * "fsl,mma8453"
* "fsl,mma8652" * "fsl,mma8652"
* "fsl,mma8653" * "fsl,mma8653"
* "fsl,fxls8471"
- reg: the I2C address of the chip - reg: the I2C address of the chip
......
NXP LPC1850 ADC bindings
Required properties:
- compatible: Should be "nxp,lpc1850-adc"
- reg: Offset and length of the register set for the ADC device
- interrupts: The interrupt number for the ADC device
- clocks: The root clock of the ADC controller
- vref-supply: The regulator supply ADC reference voltage
- resets: phandle to reset controller and line specifier
Example:
adc0: adc@400e3000 {
compatible = "nxp,lpc1850-adc";
reg = <0x400e3000 0x1000>;
interrupts = <17>;
clocks = <&ccu1 CLK_APB3_ADC0>;
vref-supply = <&reg_vdda>;
resets = <&rgu 40>;
status = "disabled";
};
Rockchip Successive Approximation Register (SAR) A/D Converter bindings Rockchip Successive Approximation Register (SAR) A/D Converter bindings
Required properties: Required properties:
- compatible: Should be "rockchip,saradc" or "rockchip,rk3066-tsadc" - compatible: should be "rockchip,<name>-saradc" or "rockchip,rk3066-tsadc"
- "rockchip,saradc": for rk3188, rk3288
- "rockchip,rk3066-tsadc": for rk3036
- "rockchip,rk3399-saradc": for rk3399
- reg: physical base address of the controller and length of memory mapped - reg: physical base address of the controller and length of memory mapped
region. region.
- interrupts: The interrupt number to the cpu. The interrupt specifier format - interrupts: The interrupt number to the cpu. The interrupt specifier format
......
NXP LPC1850 DAC bindings
Required properties:
- compatible: Should be "nxp,lpc1850-dac"
- reg: Offset and length of the register set for the ADC device
- interrupts: The interrupt number for the ADC device
- clocks: The root clock of the ADC controller
- vref-supply: The regulator supply ADC reference voltage
- resets: phandle to reset controller and line specifier
Example:
dac: dac@400e1000 {
compatible = "nxp,lpc1850-dac";
reg = <0x400e1000 0x1000>;
interrupts = <0>;
clocks = <&ccu1 CLK_APB3_DAC>;
vref-supply = <&reg_vdda>;
resets = <&rgu 42>;
status = "disabled";
};
...@@ -8,6 +8,7 @@ Required properties: ...@@ -8,6 +8,7 @@ Required properties:
Optional properties: Optional properties:
- gpios : should be device tree identifier of the magnetometer DRDY pin - gpios : should be device tree identifier of the magnetometer DRDY pin
- vdd-supply: an optional regulator that needs to be on to provide VDD
Example: Example:
...@@ -15,4 +16,5 @@ ak8975@0c { ...@@ -15,4 +16,5 @@ ak8975@0c {
compatible = "asahi-kasei,ak8975"; compatible = "asahi-kasei,ak8975";
reg = <0x0c>; reg = <0x0c>;
gpios = <&gpj0 7 0>; gpios = <&gpj0 7 0>;
vdd-supply = <&ldo_3v3_gnss>;
}; };
* Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer
driver
The node for this driver must be a child node of a SPI controller, hence
all mandatory properties described in
Documentation/devicetree/bindings/spi/spi-bus.txt
must be specified.
Required properties:
- compatible: Must be one of the following, depending on the
model:
"microchip,mcp4131-502"
"microchip,mcp4131-103"
"microchip,mcp4131-503"
"microchip,mcp4131-104"
"microchip,mcp4132-502"
"microchip,mcp4132-103"
"microchip,mcp4132-503"
"microchip,mcp4132-104"
"microchip,mcp4141-502"
"microchip,mcp4141-103"
"microchip,mcp4141-503"
"microchip,mcp4141-104"
"microchip,mcp4142-502"
"microchip,mcp4142-103"
"microchip,mcp4142-503"
"microchip,mcp4142-104"
"microchip,mcp4151-502"
"microchip,mcp4151-103"
"microchip,mcp4151-503"
"microchip,mcp4151-104"
"microchip,mcp4152-502"
"microchip,mcp4152-103"
"microchip,mcp4152-503"
"microchip,mcp4152-104"
"microchip,mcp4161-502"
"microchip,mcp4161-103"
"microchip,mcp4161-503"
"microchip,mcp4161-104"
"microchip,mcp4162-502"
"microchip,mcp4162-103"
"microchip,mcp4162-503"
"microchip,mcp4162-104"
"microchip,mcp4231-502"
"microchip,mcp4231-103"
"microchip,mcp4231-503"
"microchip,mcp4231-104"
"microchip,mcp4232-502"
"microchip,mcp4232-103"
"microchip,mcp4232-503"
"microchip,mcp4232-104"
"microchip,mcp4241-502"
"microchip,mcp4241-103"
"microchip,mcp4241-503"
"microchip,mcp4241-104"
"microchip,mcp4242-502"
"microchip,mcp4242-103"
"microchip,mcp4242-503"
"microchip,mcp4242-104"
"microchip,mcp4251-502"
"microchip,mcp4251-103"
"microchip,mcp4251-503"
"microchip,mcp4251-104"
"microchip,mcp4252-502"
"microchip,mcp4252-103"
"microchip,mcp4252-503"
"microchip,mcp4252-104"
"microchip,mcp4261-502"
"microchip,mcp4261-103"
"microchip,mcp4261-503"
"microchip,mcp4261-104"
"microchip,mcp4262-502"
"microchip,mcp4262-103"
"microchip,mcp4262-503"
"microchip,mcp4262-104"
Example:
mcp4131: mcp4131@0 {
compatible = "mcp4131-502";
reg = <0>;
spi-max-frequency = <500000>;
};
MEAS ms5611 family pressure sensors
Pressure sensors from MEAS Switzerland with SPI and I2C bus interfaces.
Required properties:
- compatible: "meas,ms5611" or "meas,ms5607"
- reg: the I2C address or SPI chip select the device will respond to
Optional properties:
- vdd-supply: an optional regulator that needs to be on to provide VDD
power to the sensor.
Example:
ms5607@77 {
compatible = "meas,ms5607";
reg = <0x77>;
vdd-supply = <&ldo_3v3_gnss>;
};
...@@ -37,6 +37,7 @@ Accelerometers: ...@@ -37,6 +37,7 @@ Accelerometers:
- st,lsm330-accel - st,lsm330-accel
- st,lsm303agr-accel - st,lsm303agr-accel
- st,lis2dh12-accel - st,lis2dh12-accel
- st,h3lis331dl-accel
Gyroscopes: Gyroscopes:
- st,l3g4200d-gyro - st,l3g4200d-gyro
......
...@@ -141,6 +141,7 @@ lsi LSI Corp. (LSI Logic) ...@@ -141,6 +141,7 @@ lsi LSI Corp. (LSI Logic)
lltc Linear Technology Corporation lltc Linear Technology Corporation
marvell Marvell Technology Group Ltd. marvell Marvell Technology Group Ltd.
maxim Maxim Integrated Products maxim Maxim Integrated Products
meas Measurement Specialties
mediatek MediaTek Inc. mediatek MediaTek Inc.
melexis Melexis N.V. melexis Melexis N.V.
merrii Merrii Technology Co., Ltd. merrii Merrii Technology Co., Ltd.
......
...@@ -5538,7 +5538,7 @@ IIO SUBSYSTEM AND DRIVERS ...@@ -5538,7 +5538,7 @@ IIO SUBSYSTEM AND DRIVERS
M: Jonathan Cameron <jic23@kernel.org> M: Jonathan Cameron <jic23@kernel.org>
R: Hartmut Knaack <knaack.h@gmx.de> R: Hartmut Knaack <knaack.h@gmx.de>
R: Lars-Peter Clausen <lars@metafoo.de> R: Lars-Peter Clausen <lars@metafoo.de>
R: Peter Meerwald <pmeerw@pmeerw.net> R: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
L: linux-iio@vger.kernel.org L: linux-iio@vger.kernel.org
S: Maintained S: Maintained
F: drivers/iio/ F: drivers/iio/
......
...@@ -64,7 +64,7 @@ config IIO_ST_ACCEL_3AXIS ...@@ -64,7 +64,7 @@ config IIO_ST_ACCEL_3AXIS
help help
Say yes here to build support for STMicroelectronics accelerometers: Say yes here to build support for STMicroelectronics accelerometers:
LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC, LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,
LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12. LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12, H3LIS331DL.
This driver can also be built as a module. If so, these modules This driver can also be built as a module. If so, these modules
will be created: will be created:
...@@ -143,7 +143,8 @@ config MMA8452 ...@@ -143,7 +143,8 @@ config MMA8452
select IIO_TRIGGERED_BUFFER select IIO_TRIGGERED_BUFFER
help help
Say yes here to build support for the following Freescale 3-axis Say yes here to build support for the following Freescale 3-axis
accelerometers: MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC. accelerometers: MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC,
FXLS8471Q.
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called mma8452. will be called mma8452.
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
...@@ -138,6 +137,7 @@ enum bmc150_accel_axis { ...@@ -138,6 +137,7 @@ enum bmc150_accel_axis {
AXIS_X, AXIS_X,
AXIS_Y, AXIS_Y,
AXIS_Z, AXIS_Z,
AXIS_MAX,
}; };
enum bmc150_power_modes { enum bmc150_power_modes {
...@@ -246,11 +246,12 @@ static const struct { ...@@ -246,11 +246,12 @@ static const struct {
{500000, BMC150_ACCEL_SLEEP_500_MS}, {500000, BMC150_ACCEL_SLEEP_500_MS},
{1000000, BMC150_ACCEL_SLEEP_1_SEC} }; {1000000, BMC150_ACCEL_SLEEP_1_SEC} };
static const struct regmap_config bmc150_i2c_regmap_conf = { const struct regmap_config bmc150_regmap_conf = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 8, .val_bits = 8,
.max_register = 0x3f, .max_register = 0x3f,
}; };
EXPORT_SYMBOL_GPL(bmc150_regmap_conf);
static int bmc150_accel_set_mode(struct bmc150_accel_data *data, static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
enum bmc150_power_modes mode, enum bmc150_power_modes mode,
...@@ -988,6 +989,7 @@ static const struct iio_event_spec bmc150_accel_event = { ...@@ -988,6 +989,7 @@ static const struct iio_event_spec bmc150_accel_event = {
.realbits = (bits), \ .realbits = (bits), \
.storagebits = 16, \ .storagebits = 16, \
.shift = 16 - (bits), \ .shift = 16 - (bits), \
.endianness = IIO_LE, \
}, \ }, \
.event_spec = &bmc150_accel_event, \ .event_spec = &bmc150_accel_event, \
.num_event_specs = 1 \ .num_event_specs = 1 \
...@@ -1104,27 +1106,23 @@ static const struct iio_info bmc150_accel_info_fifo = { ...@@ -1104,27 +1106,23 @@ static const struct iio_info bmc150_accel_info_fifo = {
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
}; };
static const unsigned long bmc150_accel_scan_masks[] = {
BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
0};
static irqreturn_t bmc150_accel_trigger_handler(int irq, void *p) static irqreturn_t bmc150_accel_trigger_handler(int irq, void *p)
{ {
struct iio_poll_func *pf = p; struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev; struct iio_dev *indio_dev = pf->indio_dev;
struct bmc150_accel_data *data = iio_priv(indio_dev); struct bmc150_accel_data *data = iio_priv(indio_dev);
int bit, ret, i = 0; int ret;
unsigned int raw_val;
mutex_lock(&data->mutex); mutex_lock(&data->mutex);
for_each_set_bit(bit, indio_dev->active_scan_mask, ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_REG_XOUT_L,
indio_dev->masklength) { data->buffer, AXIS_MAX * 2);
ret = regmap_bulk_read(data->regmap,
BMC150_ACCEL_AXIS_TO_REG(bit), &raw_val,
2);
if (ret < 0) {
mutex_unlock(&data->mutex);
goto err_read;
}
data->buffer[i++] = raw_val;
}
mutex_unlock(&data->mutex); mutex_unlock(&data->mutex);
if (ret < 0)
goto err_read;
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
pf->timestamp); pf->timestamp);
...@@ -1574,6 +1572,7 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, ...@@ -1574,6 +1572,7 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
indio_dev->channels = data->chip_info->channels; indio_dev->channels = data->chip_info->channels;
indio_dev->num_channels = data->chip_info->num_channels; indio_dev->num_channels = data->chip_info->num_channels;
indio_dev->name = name ? name : data->chip_info->name; indio_dev->name = name ? name : data->chip_info->name;
indio_dev->available_scan_masks = bmc150_accel_scan_masks;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &bmc150_accel_info; indio_dev->info = &bmc150_accel_info;
......
...@@ -28,11 +28,6 @@ ...@@ -28,11 +28,6 @@
#include "bmc150-accel.h" #include "bmc150-accel.h"
static const struct regmap_config bmc150_i2c_regmap_conf = {
.reg_bits = 8,
.val_bits = 8,
};
static int bmc150_accel_probe(struct i2c_client *client, static int bmc150_accel_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -43,7 +38,7 @@ static int bmc150_accel_probe(struct i2c_client *client, ...@@ -43,7 +38,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
i2c_check_functionality(client->adapter, i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_I2C_BLOCK); I2C_FUNC_SMBUS_READ_I2C_BLOCK);
regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf); regmap = devm_regmap_init_i2c(client, &bmc150_regmap_conf);
if (IS_ERR(regmap)) { if (IS_ERR(regmap)) {
dev_err(&client->dev, "Failed to initialize i2c regmap\n"); dev_err(&client->dev, "Failed to initialize i2c regmap\n");
return PTR_ERR(regmap); return PTR_ERR(regmap);
......
...@@ -25,18 +25,12 @@ ...@@ -25,18 +25,12 @@
#include "bmc150-accel.h" #include "bmc150-accel.h"
static const struct regmap_config bmc150_spi_regmap_conf = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0x3f,
};
static int bmc150_accel_probe(struct spi_device *spi) static int bmc150_accel_probe(struct spi_device *spi)
{ {
struct regmap *regmap; struct regmap *regmap;
const struct spi_device_id *id = spi_get_device_id(spi); const struct spi_device_id *id = spi_get_device_id(spi);
regmap = devm_regmap_init_spi(spi, &bmc150_spi_regmap_conf); regmap = devm_regmap_init_spi(spi, &bmc150_regmap_conf);
if (IS_ERR(regmap)) { if (IS_ERR(regmap)) {
dev_err(&spi->dev, "Failed to initialize spi regmap\n"); dev_err(&spi->dev, "Failed to initialize spi regmap\n");
return PTR_ERR(regmap); return PTR_ERR(regmap);
......
...@@ -16,5 +16,6 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, ...@@ -16,5 +16,6 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
const char *name, bool block_supported); const char *name, bool block_supported);
int bmc150_accel_core_remove(struct device *dev); int bmc150_accel_core_remove(struct device *dev);
extern const struct dev_pm_ops bmc150_accel_pm_ops; extern const struct dev_pm_ops bmc150_accel_pm_ops;
extern const struct regmap_config bmc150_regmap_conf;
#endif /* _BMC150_ACCEL_H_ */ #endif /* _BMC150_ACCEL_H_ */
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
...@@ -115,6 +114,7 @@ enum kxcjk1013_axis { ...@@ -115,6 +114,7 @@ enum kxcjk1013_axis {
AXIS_X, AXIS_X,
AXIS_Y, AXIS_Y,
AXIS_Z, AXIS_Z,
AXIS_MAX,
}; };
enum kxcjk1013_mode { enum kxcjk1013_mode {
...@@ -922,7 +922,7 @@ static const struct iio_event_spec kxcjk1013_event = { ...@@ -922,7 +922,7 @@ static const struct iio_event_spec kxcjk1013_event = {
.realbits = 12, \ .realbits = 12, \
.storagebits = 16, \ .storagebits = 16, \
.shift = 4, \ .shift = 4, \
.endianness = IIO_CPU, \ .endianness = IIO_LE, \
}, \ }, \
.event_spec = &kxcjk1013_event, \ .event_spec = &kxcjk1013_event, \
.num_event_specs = 1 \ .num_event_specs = 1 \
...@@ -953,25 +953,23 @@ static const struct iio_info kxcjk1013_info = { ...@@ -953,25 +953,23 @@ static const struct iio_info kxcjk1013_info = {
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
}; };
static const unsigned long kxcjk1013_scan_masks[] = {0x7, 0};
static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p) static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p)
{ {
struct iio_poll_func *pf = p; struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev; struct iio_dev *indio_dev = pf->indio_dev;
struct kxcjk1013_data *data = iio_priv(indio_dev); struct kxcjk1013_data *data = iio_priv(indio_dev);
int bit, ret, i = 0; int ret;
mutex_lock(&data->mutex); mutex_lock(&data->mutex);
ret = i2c_smbus_read_i2c_block_data_or_emulated(data->client,
for_each_set_bit(bit, indio_dev->active_scan_mask, KXCJK1013_REG_XOUT_L,
indio_dev->masklength) { AXIS_MAX * 2,
ret = kxcjk1013_get_acc_reg(data, bit); (u8 *)data->buffer);
if (ret < 0) {
mutex_unlock(&data->mutex);
goto err;
}
data->buffer[i++] = ret;
}
mutex_unlock(&data->mutex); mutex_unlock(&data->mutex);
if (ret < 0)
goto err;
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
data->timestamp); data->timestamp);
...@@ -1204,6 +1202,7 @@ static int kxcjk1013_probe(struct i2c_client *client, ...@@ -1204,6 +1202,7 @@ static int kxcjk1013_probe(struct i2c_client *client,
indio_dev->dev.parent = &client->dev; indio_dev->dev.parent = &client->dev;
indio_dev->channels = kxcjk1013_channels; indio_dev->channels = kxcjk1013_channels;
indio_dev->num_channels = ARRAY_SIZE(kxcjk1013_channels); indio_dev->num_channels = ARRAY_SIZE(kxcjk1013_channels);
indio_dev->available_scan_masks = kxcjk1013_scan_masks;
indio_dev->name = name; indio_dev->name = name;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &kxcjk1013_info; indio_dev->info = &kxcjk1013_info;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* MMA8453Q (10 bit) * MMA8453Q (10 bit)
* MMA8652FC (12 bit) * MMA8652FC (12 bit)
* MMA8653FC (10 bit) * MMA8653FC (10 bit)
* FXLS8471Q (14 bit)
* *
* Copyright 2015 Martin Kepplinger <martin.kepplinger@theobroma-systems.com> * Copyright 2015 Martin Kepplinger <martin.kepplinger@theobroma-systems.com>
* Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net> * Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net>
...@@ -16,7 +17,7 @@ ...@@ -16,7 +17,7 @@
* *
* 7-bit I2C slave address 0x1c/0x1d (pin selectable) * 7-bit I2C slave address 0x1c/0x1d (pin selectable)
* *
* TODO: orientation events, autosleep * TODO: orientation events
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -31,6 +32,7 @@ ...@@ -31,6 +32,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/pm_runtime.h>
#define MMA8452_STATUS 0x00 #define MMA8452_STATUS 0x00
#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
...@@ -91,6 +93,9 @@ ...@@ -91,6 +93,9 @@
#define MMA8453_DEVICE_ID 0x3a #define MMA8453_DEVICE_ID 0x3a
#define MMA8652_DEVICE_ID 0x4a #define MMA8652_DEVICE_ID 0x4a
#define MMA8653_DEVICE_ID 0x5a #define MMA8653_DEVICE_ID 0x5a
#define FXLS8471_DEVICE_ID 0x6a
#define MMA8452_AUTO_SUSPEND_DELAY_MS 2000
struct mma8452_data { struct mma8452_data {
struct i2c_client *client; struct i2c_client *client;
...@@ -172,6 +177,31 @@ static int mma8452_drdy(struct mma8452_data *data) ...@@ -172,6 +177,31 @@ static int mma8452_drdy(struct mma8452_data *data)
return -EIO; return -EIO;
} }
static int mma8452_set_runtime_pm_state(struct i2c_client *client, bool on)
{
#ifdef CONFIG_PM
int ret;
if (on) {
ret = pm_runtime_get_sync(&client->dev);
} else {
pm_runtime_mark_last_busy(&client->dev);
ret = pm_runtime_put_autosuspend(&client->dev);
}
if (ret < 0) {
dev_err(&client->dev,
"failed to change power state to %d\n", on);
if (on)
pm_runtime_put_noidle(&client->dev);
return ret;
}
#endif
return 0;
}
static int mma8452_read(struct mma8452_data *data, __be16 buf[3]) static int mma8452_read(struct mma8452_data *data, __be16 buf[3])
{ {
int ret = mma8452_drdy(data); int ret = mma8452_drdy(data);
...@@ -179,8 +209,16 @@ static int mma8452_read(struct mma8452_data *data, __be16 buf[3]) ...@@ -179,8 +209,16 @@ static int mma8452_read(struct mma8452_data *data, __be16 buf[3])
if (ret < 0) if (ret < 0)
return ret; return ret;
return i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X, ret = mma8452_set_runtime_pm_state(data->client, true);
3 * sizeof(__be16), (u8 *)buf); if (ret)
return ret;
ret = i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X,
3 * sizeof(__be16), (u8 *)buf);
ret = mma8452_set_runtime_pm_state(data->client, false);
return ret;
} }
static ssize_t mma8452_show_int_plus_micros(char *buf, const int (*vals)[2], static ssize_t mma8452_show_int_plus_micros(char *buf, const int (*vals)[2],
...@@ -357,7 +395,8 @@ static int mma8452_read_raw(struct iio_dev *indio_dev, ...@@ -357,7 +395,8 @@ static int mma8452_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT_PLUS_MICRO; return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_CALIBBIAS:
ret = i2c_smbus_read_byte_data(data->client, ret = i2c_smbus_read_byte_data(data->client,
MMA8452_OFF_X + chan->scan_index); MMA8452_OFF_X +
chan->scan_index);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -392,24 +431,47 @@ static int mma8452_active(struct mma8452_data *data) ...@@ -392,24 +431,47 @@ static int mma8452_active(struct mma8452_data *data)
data->ctrl_reg1); data->ctrl_reg1);
} }
/* returns >0 if active, 0 if in standby and <0 on error */
static int mma8452_is_active(struct mma8452_data *data)
{
int reg;
reg = i2c_smbus_read_byte_data(data->client, MMA8452_CTRL_REG1);
if (reg < 0)
return reg;
return reg & MMA8452_CTRL_ACTIVE;
}
static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val) static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val)
{ {
int ret; int ret;
int is_active;
mutex_lock(&data->lock); mutex_lock(&data->lock);
/* config can only be changed when in standby */ is_active = mma8452_is_active(data);
ret = mma8452_standby(data); if (is_active < 0) {
if (ret < 0) ret = is_active;
goto fail; goto fail;
}
/* config can only be changed when in standby */
if (is_active > 0) {
ret = mma8452_standby(data);
if (ret < 0)
goto fail;
}
ret = i2c_smbus_write_byte_data(data->client, reg, val); ret = i2c_smbus_write_byte_data(data->client, reg, val);
if (ret < 0) if (ret < 0)
goto fail; goto fail;
ret = mma8452_active(data); if (is_active > 0) {
if (ret < 0) ret = mma8452_active(data);
goto fail; if (ret < 0)
goto fail;
}
ret = 0; ret = 0;
fail: fail:
...@@ -418,7 +480,7 @@ static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val) ...@@ -418,7 +480,7 @@ static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val)
return ret; return ret;
} }
/* returns >0 if in freefall mode, 0 if not or <0 if an error occured */ /* returns >0 if in freefall mode, 0 if not or <0 if an error occurred */
static int mma8452_freefall_mode_enabled(struct mma8452_data *data) static int mma8452_freefall_mode_enabled(struct mma8452_data *data)
{ {
int val; int val;
...@@ -668,7 +730,8 @@ static int mma8452_read_event_config(struct iio_dev *indio_dev, ...@@ -668,7 +730,8 @@ static int mma8452_read_event_config(struct iio_dev *indio_dev,
if (ret < 0) if (ret < 0)
return ret; return ret;
return !!(ret & BIT(chan->scan_index + chip->ev_cfg_chan_shift)); return !!(ret & BIT(chan->scan_index +
chip->ev_cfg_chan_shift));
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -682,7 +745,11 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev, ...@@ -682,7 +745,11 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev,
{ {
struct mma8452_data *data = iio_priv(indio_dev); struct mma8452_data *data = iio_priv(indio_dev);
const struct mma_chip_info *chip = data->chip_info; const struct mma_chip_info *chip = data->chip_info;
int val; int val, ret;
ret = mma8452_set_runtime_pm_state(data->client, state);
if (ret)
return ret;
switch (dir) { switch (dir) {
case IIO_EV_DIR_FALLING: case IIO_EV_DIR_FALLING:
...@@ -990,6 +1057,7 @@ enum { ...@@ -990,6 +1057,7 @@ enum {
mma8453, mma8453,
mma8652, mma8652,
mma8653, mma8653,
fxls8471,
}; };
static const struct mma_chip_info mma_chip_info_table[] = { static const struct mma_chip_info mma_chip_info_table[] = {
...@@ -1003,7 +1071,7 @@ static const struct mma_chip_info mma_chip_info_table[] = { ...@@ -1003,7 +1071,7 @@ static const struct mma_chip_info mma_chip_info_table[] = {
* bit. * bit.
* The userspace interface uses m/s^2 and we declare micro units * The userspace interface uses m/s^2 and we declare micro units
* So scale factor for 12 bit here is given by: * So scale factor for 12 bit here is given by:
* g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665 * g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
*/ */
.mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} }, .mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} },
.ev_cfg = MMA8452_TRANSIENT_CFG, .ev_cfg = MMA8452_TRANSIENT_CFG,
...@@ -1081,6 +1149,22 @@ static const struct mma_chip_info mma_chip_info_table[] = { ...@@ -1081,6 +1149,22 @@ static const struct mma_chip_info mma_chip_info_table[] = {
.ev_ths_mask = MMA8452_FF_MT_THS_MASK, .ev_ths_mask = MMA8452_FF_MT_THS_MASK,
.ev_count = MMA8452_FF_MT_COUNT, .ev_count = MMA8452_FF_MT_COUNT,
}, },
[fxls8471] = {
.chip_id = FXLS8471_DEVICE_ID,
.channels = mma8451_channels,
.num_channels = ARRAY_SIZE(mma8451_channels),
.mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} },
.ev_cfg = MMA8452_TRANSIENT_CFG,
.ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
.ev_cfg_chan_shift = 1,
.ev_src = MMA8452_TRANSIENT_SRC,
.ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
.ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
.ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
.ev_ths = MMA8452_TRANSIENT_THS,
.ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
.ev_count = MMA8452_TRANSIENT_COUNT,
},
}; };
static struct attribute *mma8452_attributes[] = { static struct attribute *mma8452_attributes[] = {
...@@ -1114,7 +1198,11 @@ static int mma8452_data_rdy_trigger_set_state(struct iio_trigger *trig, ...@@ -1114,7 +1198,11 @@ static int mma8452_data_rdy_trigger_set_state(struct iio_trigger *trig,
{ {
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
struct mma8452_data *data = iio_priv(indio_dev); struct mma8452_data *data = iio_priv(indio_dev);
int reg; int reg, ret;
ret = mma8452_set_runtime_pm_state(data->client, state);
if (ret)
return ret;
reg = i2c_smbus_read_byte_data(data->client, MMA8452_CTRL_REG4); reg = i2c_smbus_read_byte_data(data->client, MMA8452_CTRL_REG4);
if (reg < 0) if (reg < 0)
...@@ -1206,6 +1294,7 @@ static const struct of_device_id mma8452_dt_ids[] = { ...@@ -1206,6 +1294,7 @@ static const struct of_device_id mma8452_dt_ids[] = {
{ .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] }, { .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] },
{ .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] }, { .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] },
{ .compatible = "fsl,mma8653", .data = &mma_chip_info_table[mma8653] }, { .compatible = "fsl,mma8653", .data = &mma_chip_info_table[mma8653] },
{ .compatible = "fsl,fxls8471", .data = &mma_chip_info_table[fxls8471] },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, mma8452_dt_ids); MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
...@@ -1243,6 +1332,7 @@ static int mma8452_probe(struct i2c_client *client, ...@@ -1243,6 +1332,7 @@ static int mma8452_probe(struct i2c_client *client,
case MMA8453_DEVICE_ID: case MMA8453_DEVICE_ID:
case MMA8652_DEVICE_ID: case MMA8652_DEVICE_ID:
case MMA8653_DEVICE_ID: case MMA8653_DEVICE_ID:
case FXLS8471_DEVICE_ID:
if (ret == data->chip_info->chip_id) if (ret == data->chip_info->chip_id)
break; break;
default: default:
...@@ -1340,6 +1430,15 @@ static int mma8452_probe(struct i2c_client *client, ...@@ -1340,6 +1430,15 @@ static int mma8452_probe(struct i2c_client *client,
goto buffer_cleanup; goto buffer_cleanup;
} }
ret = pm_runtime_set_active(&client->dev);
if (ret < 0)
goto buffer_cleanup;
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev,
MMA8452_AUTO_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(&client->dev);
ret = iio_device_register(indio_dev); ret = iio_device_register(indio_dev);
if (ret < 0) if (ret < 0)
goto buffer_cleanup; goto buffer_cleanup;
...@@ -1364,6 +1463,11 @@ static int mma8452_remove(struct i2c_client *client) ...@@ -1364,6 +1463,11 @@ static int mma8452_remove(struct i2c_client *client)
struct iio_dev *indio_dev = i2c_get_clientdata(client); struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev); iio_device_unregister(indio_dev);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
pm_runtime_put_noidle(&client->dev);
iio_triggered_buffer_cleanup(indio_dev); iio_triggered_buffer_cleanup(indio_dev);
mma8452_trigger_cleanup(indio_dev); mma8452_trigger_cleanup(indio_dev);
mma8452_standby(iio_priv(indio_dev)); mma8452_standby(iio_priv(indio_dev));
...@@ -1371,6 +1475,45 @@ static int mma8452_remove(struct i2c_client *client) ...@@ -1371,6 +1475,45 @@ static int mma8452_remove(struct i2c_client *client)
return 0; return 0;
} }
#ifdef CONFIG_PM
static int mma8452_runtime_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct mma8452_data *data = iio_priv(indio_dev);
int ret;
mutex_lock(&data->lock);
ret = mma8452_standby(data);
mutex_unlock(&data->lock);
if (ret < 0) {
dev_err(&data->client->dev, "powering off device failed\n");
return -EAGAIN;
}
return 0;
}
static int mma8452_runtime_resume(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct mma8452_data *data = iio_priv(indio_dev);
int ret, sleep_val;
ret = mma8452_active(data);
if (ret < 0)
return ret;
ret = mma8452_get_odr_index(data);
sleep_val = 1000 / mma8452_samp_freq[ret][0];
if (sleep_val < 20)
usleep_range(sleep_val * 1000, 20000);
else
msleep_interruptible(sleep_val);
return 0;
}
#endif
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int mma8452_suspend(struct device *dev) static int mma8452_suspend(struct device *dev)
{ {
...@@ -1383,18 +1526,21 @@ static int mma8452_resume(struct device *dev) ...@@ -1383,18 +1526,21 @@ static int mma8452_resume(struct device *dev)
return mma8452_active(iio_priv(i2c_get_clientdata( return mma8452_active(iio_priv(i2c_get_clientdata(
to_i2c_client(dev)))); to_i2c_client(dev))));
} }
static SIMPLE_DEV_PM_OPS(mma8452_pm_ops, mma8452_suspend, mma8452_resume);
#define MMA8452_PM_OPS (&mma8452_pm_ops)
#else
#define MMA8452_PM_OPS NULL
#endif #endif
static const struct dev_pm_ops mma8452_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(mma8452_suspend, mma8452_resume)
SET_RUNTIME_PM_OPS(mma8452_runtime_suspend,
mma8452_runtime_resume, NULL)
};
static const struct i2c_device_id mma8452_id[] = { static const struct i2c_device_id mma8452_id[] = {
{ "mma8451", mma8451 },
{ "mma8452", mma8452 }, { "mma8452", mma8452 },
{ "mma8453", mma8453 }, { "mma8453", mma8453 },
{ "mma8652", mma8652 }, { "mma8652", mma8652 },
{ "mma8653", mma8653 }, { "mma8653", mma8653 },
{ "fxls8471", fxls8471 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, mma8452_id); MODULE_DEVICE_TABLE(i2c, mma8452_id);
...@@ -1403,7 +1549,7 @@ static struct i2c_driver mma8452_driver = { ...@@ -1403,7 +1549,7 @@ static struct i2c_driver mma8452_driver = {
.driver = { .driver = {
.name = "mma8452", .name = "mma8452",
.of_match_table = of_match_ptr(mma8452_dt_ids), .of_match_table = of_match_ptr(mma8452_dt_ids),
.pm = MMA8452_PM_OPS, .pm = &mma8452_pm_ops,
}, },
.probe = mma8452_probe, .probe = mma8452_probe,
.remove = mma8452_remove, .remove = mma8452_remove,
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
#include <linux/iio/events.h> #include <linux/iio/events.h>
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h> #include <linux/iio/trigger.h>
...@@ -380,31 +379,6 @@ static const struct iio_trigger_ops mxc4005_trigger_ops = { ...@@ -380,31 +379,6 @@ static const struct iio_trigger_ops mxc4005_trigger_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static int mxc4005_gpio_probe(struct i2c_client *client,
struct mxc4005_data *data)
{
struct device *dev;
struct gpio_desc *gpio;
int ret;
if (!client)
return -EINVAL;
dev = &client->dev;
gpio = devm_gpiod_get_index(dev, "mxc4005_int", 0, GPIOD_IN);
if (IS_ERR(gpio)) {
dev_err(dev, "failed to get acpi gpio index\n");
return PTR_ERR(gpio);
}
ret = gpiod_to_irq(gpio);
dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
return ret;
}
static int mxc4005_chip_init(struct mxc4005_data *data) static int mxc4005_chip_init(struct mxc4005_data *data)
{ {
int ret; int ret;
...@@ -470,9 +444,6 @@ static int mxc4005_probe(struct i2c_client *client, ...@@ -470,9 +444,6 @@ static int mxc4005_probe(struct i2c_client *client,
return ret; return ret;
} }
if (client->irq < 0)
client->irq = mxc4005_gpio_probe(client, data);
if (client->irq > 0) { if (client->irq > 0) {
data->dready_trig = devm_iio_trigger_alloc(&client->dev, data->dready_trig = devm_iio_trigger_alloc(&client->dev,
"%s-dev%d", "%s-dev%d",
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/iio/common/st_sensors.h> #include <linux/iio/common/st_sensors.h>
#define H3LIS331DL_DRIVER_NAME "h3lis331dl_accel"
#define LIS3LV02DL_ACCEL_DEV_NAME "lis3lv02dl_accel" #define LIS3LV02DL_ACCEL_DEV_NAME "lis3lv02dl_accel"
#define LSM303DLHC_ACCEL_DEV_NAME "lsm303dlhc_accel" #define LSM303DLHC_ACCEL_DEV_NAME "lsm303dlhc_accel"
#define LIS3DH_ACCEL_DEV_NAME "lis3dh" #define LIS3DH_ACCEL_DEV_NAME "lis3dh"
......
...@@ -39,6 +39,9 @@ ...@@ -39,6 +39,9 @@
#define ST_ACCEL_FS_AVL_6G 6 #define ST_ACCEL_FS_AVL_6G 6
#define ST_ACCEL_FS_AVL_8G 8 #define ST_ACCEL_FS_AVL_8G 8
#define ST_ACCEL_FS_AVL_16G 16 #define ST_ACCEL_FS_AVL_16G 16
#define ST_ACCEL_FS_AVL_100G 100
#define ST_ACCEL_FS_AVL_200G 200
#define ST_ACCEL_FS_AVL_400G 400
/* CUSTOM VALUES FOR SENSOR 1 */ /* CUSTOM VALUES FOR SENSOR 1 */
#define ST_ACCEL_1_WAI_EXP 0x33 #define ST_ACCEL_1_WAI_EXP 0x33
...@@ -181,6 +184,33 @@ ...@@ -181,6 +184,33 @@
#define ST_ACCEL_5_IG1_EN_MASK 0x08 #define ST_ACCEL_5_IG1_EN_MASK 0x08
#define ST_ACCEL_5_MULTIREAD_BIT false #define ST_ACCEL_5_MULTIREAD_BIT false
/* CUSTOM VALUES FOR SENSOR 6 */
#define ST_ACCEL_6_WAI_EXP 0x32
#define ST_ACCEL_6_ODR_ADDR 0x20
#define ST_ACCEL_6_ODR_MASK 0x18
#define ST_ACCEL_6_ODR_AVL_50HZ_VAL 0x00
#define ST_ACCEL_6_ODR_AVL_100HZ_VAL 0x01
#define ST_ACCEL_6_ODR_AVL_400HZ_VAL 0x02
#define ST_ACCEL_6_ODR_AVL_1000HZ_VAL 0x03
#define ST_ACCEL_6_PW_ADDR 0x20
#define ST_ACCEL_6_PW_MASK 0x20
#define ST_ACCEL_6_FS_ADDR 0x23
#define ST_ACCEL_6_FS_MASK 0x30
#define ST_ACCEL_6_FS_AVL_100_VAL 0x00
#define ST_ACCEL_6_FS_AVL_200_VAL 0x01
#define ST_ACCEL_6_FS_AVL_400_VAL 0x03
#define ST_ACCEL_6_FS_AVL_100_GAIN IIO_G_TO_M_S_2(49000)
#define ST_ACCEL_6_FS_AVL_200_GAIN IIO_G_TO_M_S_2(98000)
#define ST_ACCEL_6_FS_AVL_400_GAIN IIO_G_TO_M_S_2(195000)
#define ST_ACCEL_6_BDU_ADDR 0x23
#define ST_ACCEL_6_BDU_MASK 0x80
#define ST_ACCEL_6_DRDY_IRQ_ADDR 0x22
#define ST_ACCEL_6_DRDY_IRQ_INT1_MASK 0x02
#define ST_ACCEL_6_DRDY_IRQ_INT2_MASK 0x10
#define ST_ACCEL_6_IHL_IRQ_ADDR 0x22
#define ST_ACCEL_6_IHL_IRQ_MASK 0x80
#define ST_ACCEL_6_MULTIREAD_BIT true
static const struct iio_chan_spec st_accel_8bit_channels[] = { static const struct iio_chan_spec st_accel_8bit_channels[] = {
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
...@@ -557,6 +587,68 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { ...@@ -557,6 +587,68 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT, .multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT,
.bootime = 2, /* guess */ .bootime = 2, /* guess */
}, },
{
.wai = ST_ACCEL_6_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = H3LIS331DL_DRIVER_NAME,
},
.ch = (struct iio_chan_spec *)st_accel_12bit_channels,
.odr = {
.addr = ST_ACCEL_6_ODR_ADDR,
.mask = ST_ACCEL_6_ODR_MASK,
.odr_avl = {
{ 50, ST_ACCEL_6_ODR_AVL_50HZ_VAL },
{ 100, ST_ACCEL_6_ODR_AVL_100HZ_VAL, },
{ 400, ST_ACCEL_6_ODR_AVL_400HZ_VAL, },
{ 1000, ST_ACCEL_6_ODR_AVL_1000HZ_VAL, },
},
},
.pw = {
.addr = ST_ACCEL_6_PW_ADDR,
.mask = ST_ACCEL_6_PW_MASK,
.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
},
.enable_axis = {
.addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
},
.fs = {
.addr = ST_ACCEL_6_FS_ADDR,
.mask = ST_ACCEL_6_FS_MASK,
.fs_avl = {
[0] = {
.num = ST_ACCEL_FS_AVL_100G,
.value = ST_ACCEL_6_FS_AVL_100_VAL,
.gain = ST_ACCEL_6_FS_AVL_100_GAIN,
},
[1] = {
.num = ST_ACCEL_FS_AVL_200G,
.value = ST_ACCEL_6_FS_AVL_200_VAL,
.gain = ST_ACCEL_6_FS_AVL_200_GAIN,
},
[2] = {
.num = ST_ACCEL_FS_AVL_400G,
.value = ST_ACCEL_6_FS_AVL_400_VAL,
.gain = ST_ACCEL_6_FS_AVL_400_GAIN,
},
},
},
.bdu = {
.addr = ST_ACCEL_6_BDU_ADDR,
.mask = ST_ACCEL_6_BDU_MASK,
},
.drdy_irq = {
.addr = ST_ACCEL_6_DRDY_IRQ_ADDR,
.mask_int1 = ST_ACCEL_6_DRDY_IRQ_INT1_MASK,
.mask_int2 = ST_ACCEL_6_DRDY_IRQ_INT2_MASK,
.addr_ihl = ST_ACCEL_6_IHL_IRQ_ADDR,
.mask_ihl = ST_ACCEL_6_IHL_IRQ_MASK,
},
.multi_read_bit = ST_ACCEL_6_MULTIREAD_BIT,
.bootime = 2,
},
}; };
static int st_accel_read_raw(struct iio_dev *indio_dev, static int st_accel_read_raw(struct iio_dev *indio_dev,
......
...@@ -76,6 +76,10 @@ static const struct of_device_id st_accel_of_match[] = { ...@@ -76,6 +76,10 @@ static const struct of_device_id st_accel_of_match[] = {
.compatible = "st,lis2dh12-accel", .compatible = "st,lis2dh12-accel",
.data = LIS2DH12_ACCEL_DEV_NAME, .data = LIS2DH12_ACCEL_DEV_NAME,
}, },
{
.compatible = "st,h3lis331dl-accel",
.data = H3LIS331DL_DRIVER_NAME,
},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, st_accel_of_match); MODULE_DEVICE_TABLE(of, st_accel_of_match);
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
*/ */
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
*/ */
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
......
...@@ -134,6 +134,7 @@ config AT91_ADC ...@@ -134,6 +134,7 @@ config AT91_ADC
config AT91_SAMA5D2_ADC config AT91_SAMA5D2_ADC
tristate "Atmel AT91 SAMA5D2 ADC" tristate "Atmel AT91 SAMA5D2 ADC"
depends on ARCH_AT91 || COMPILE_TEST depends on ARCH_AT91 || COMPILE_TEST
depends on HAS_IOMEM
help help
Say yes here to build support for Atmel SAMA5D2 ADC which is Say yes here to build support for Atmel SAMA5D2 ADC which is
available on SAMA5D2 SoC family. available on SAMA5D2 SoC family.
...@@ -241,6 +242,16 @@ config LP8788_ADC ...@@ -241,6 +242,16 @@ config LP8788_ADC
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called lp8788_adc. called lp8788_adc.
config LPC18XX_ADC
tristate "NXP LPC18xx ADC driver"
depends on ARCH_LPC18XX || COMPILE_TEST
depends on OF && HAS_IOMEM
help
Say yes here to build support for NXP LPC18XX ADC.
To compile this driver as a module, choose M here: the module will be
called lpc18xx_adc.
config MAX1027 config MAX1027
tristate "Maxim max1027 ADC driver" tristate "Maxim max1027 ADC driver"
depends on SPI depends on SPI
......
...@@ -25,6 +25,7 @@ obj-$(CONFIG_HI8435) += hi8435.o ...@@ -25,6 +25,7 @@ obj-$(CONFIG_HI8435) += hi8435.o
obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1027) += max1027.o
obj-$(CONFIG_MAX1363) += max1363.o obj-$(CONFIG_MAX1363) += max1363.o
obj-$(CONFIG_MCP320X) += mcp320x.o obj-$(CONFIG_MCP320X) += mcp320x.o
......
...@@ -66,8 +66,10 @@ ...@@ -66,8 +66,10 @@
#define AT91_SAMA5D2_MR_PRESCAL(v) ((v) << AT91_SAMA5D2_MR_PRESCAL_OFFSET) #define AT91_SAMA5D2_MR_PRESCAL(v) ((v) << AT91_SAMA5D2_MR_PRESCAL_OFFSET)
#define AT91_SAMA5D2_MR_PRESCAL_OFFSET 8 #define AT91_SAMA5D2_MR_PRESCAL_OFFSET 8
#define AT91_SAMA5D2_MR_PRESCAL_MAX 0xff #define AT91_SAMA5D2_MR_PRESCAL_MAX 0xff
#define AT91_SAMA5D2_MR_PRESCAL_MASK GENMASK(15, 8)
/* Startup Time */ /* Startup Time */
#define AT91_SAMA5D2_MR_STARTUP(v) ((v) << 16) #define AT91_SAMA5D2_MR_STARTUP(v) ((v) << 16)
#define AT91_SAMA5D2_MR_STARTUP_MASK GENMASK(19, 16)
/* Analog Change */ /* Analog Change */
#define AT91_SAMA5D2_MR_ANACH BIT(23) #define AT91_SAMA5D2_MR_ANACH BIT(23)
/* Tracking Time */ /* Tracking Time */
...@@ -92,13 +94,13 @@ ...@@ -92,13 +94,13 @@
/* Last Converted Data Register */ /* Last Converted Data Register */
#define AT91_SAMA5D2_LCDR 0x20 #define AT91_SAMA5D2_LCDR 0x20
/* Interrupt Enable Register */ /* Interrupt Enable Register */
#define AT91_SAMA5D2_IER 0x24 #define AT91_SAMA5D2_IER 0x24
/* Interrupt Disable Register */ /* Interrupt Disable Register */
#define AT91_SAMA5D2_IDR 0x28 #define AT91_SAMA5D2_IDR 0x28
/* Interrupt Mask Register */ /* Interrupt Mask Register */
#define AT91_SAMA5D2_IMR 0x2c #define AT91_SAMA5D2_IMR 0x2c
/* Interrupt Status Register */ /* Interrupt Status Register */
#define AT91_SAMA5D2_ISR 0x30 #define AT91_SAMA5D2_ISR 0x30
/* Last Channel Trigger Mode Register */ /* Last Channel Trigger Mode Register */
#define AT91_SAMA5D2_LCTMR 0x34 #define AT91_SAMA5D2_LCTMR 0x34
/* Last Channel Compare Window Register */ /* Last Channel Compare Window Register */
...@@ -106,17 +108,20 @@ ...@@ -106,17 +108,20 @@
/* Overrun Status Register */ /* Overrun Status Register */
#define AT91_SAMA5D2_OVER 0x3c #define AT91_SAMA5D2_OVER 0x3c
/* Extended Mode Register */ /* Extended Mode Register */
#define AT91_SAMA5D2_EMR 0x40 #define AT91_SAMA5D2_EMR 0x40
/* Compare Window Register */ /* Compare Window Register */
#define AT91_SAMA5D2_CWR 0x44 #define AT91_SAMA5D2_CWR 0x44
/* Channel Gain Register */ /* Channel Gain Register */
#define AT91_SAMA5D2_CGR 0x48 #define AT91_SAMA5D2_CGR 0x48
/* Channel Offset Register */ /* Channel Offset Register */
#define AT91_SAMA5D2_COR 0x4c #define AT91_SAMA5D2_COR 0x4c
#define AT91_SAMA5D2_COR_DIFF_OFFSET 16
/* Channel Data Register 0 */ /* Channel Data Register 0 */
#define AT91_SAMA5D2_CDR0 0x50 #define AT91_SAMA5D2_CDR0 0x50
/* Analog Control Register */ /* Analog Control Register */
#define AT91_SAMA5D2_ACR 0x94 #define AT91_SAMA5D2_ACR 0x94
/* Touchscreen Mode Register */ /* Touchscreen Mode Register */
#define AT91_SAMA5D2_TSMR 0xb0 #define AT91_SAMA5D2_TSMR 0xb0
/* Touchscreen X Position Register */ /* Touchscreen X Position Register */
...@@ -130,7 +135,7 @@ ...@@ -130,7 +135,7 @@
/* Correction Select Register */ /* Correction Select Register */
#define AT91_SAMA5D2_COSR 0xd0 #define AT91_SAMA5D2_COSR 0xd0
/* Correction Value Register */ /* Correction Value Register */
#define AT91_SAMA5D2_CVR 0xd4 #define AT91_SAMA5D2_CVR 0xd4
/* Channel Error Correction Register */ /* Channel Error Correction Register */
#define AT91_SAMA5D2_CECR 0xd8 #define AT91_SAMA5D2_CECR 0xd8
/* Write Protection Mode Register */ /* Write Protection Mode Register */
...@@ -140,7 +145,7 @@ ...@@ -140,7 +145,7 @@
/* Version Register */ /* Version Register */
#define AT91_SAMA5D2_VERSION 0xfc #define AT91_SAMA5D2_VERSION 0xfc
#define AT91_AT91_SAMA5D2_CHAN(num, addr) \ #define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \
{ \ { \
.type = IIO_VOLTAGE, \ .type = IIO_VOLTAGE, \
.channel = num, \ .channel = num, \
...@@ -156,6 +161,24 @@ ...@@ -156,6 +161,24 @@
.indexed = 1, \ .indexed = 1, \
} }
#define AT91_SAMA5D2_CHAN_DIFF(num, num2, addr) \
{ \
.type = IIO_VOLTAGE, \
.differential = 1, \
.channel = num, \
.channel2 = num2, \
.address = addr, \
.scan_type = { \
.sign = 's', \
.realbits = 12, \
}, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
.datasheet_name = "CH"#num"-CH"#num2, \
.indexed = 1, \
}
#define at91_adc_readl(st, reg) readl_relaxed(st->base + reg) #define at91_adc_readl(st, reg) readl_relaxed(st->base + reg)
#define at91_adc_writel(st, reg, val) writel_relaxed(val, st->base + reg) #define at91_adc_writel(st, reg, val) writel_relaxed(val, st->base + reg)
...@@ -185,18 +208,24 @@ struct at91_adc_state { ...@@ -185,18 +208,24 @@ struct at91_adc_state {
}; };
static const struct iio_chan_spec at91_adc_channels[] = { static const struct iio_chan_spec at91_adc_channels[] = {
AT91_AT91_SAMA5D2_CHAN(0, 0x50), AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
AT91_AT91_SAMA5D2_CHAN(1, 0x54), AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
AT91_AT91_SAMA5D2_CHAN(2, 0x58), AT91_SAMA5D2_CHAN_SINGLE(2, 0x58),
AT91_AT91_SAMA5D2_CHAN(3, 0x5c), AT91_SAMA5D2_CHAN_SINGLE(3, 0x5c),
AT91_AT91_SAMA5D2_CHAN(4, 0x60), AT91_SAMA5D2_CHAN_SINGLE(4, 0x60),
AT91_AT91_SAMA5D2_CHAN(5, 0x64), AT91_SAMA5D2_CHAN_SINGLE(5, 0x64),
AT91_AT91_SAMA5D2_CHAN(6, 0x68), AT91_SAMA5D2_CHAN_SINGLE(6, 0x68),
AT91_AT91_SAMA5D2_CHAN(7, 0x6c), AT91_SAMA5D2_CHAN_SINGLE(7, 0x6c),
AT91_AT91_SAMA5D2_CHAN(8, 0x70), AT91_SAMA5D2_CHAN_SINGLE(8, 0x70),
AT91_AT91_SAMA5D2_CHAN(9, 0x74), AT91_SAMA5D2_CHAN_SINGLE(9, 0x74),
AT91_AT91_SAMA5D2_CHAN(10, 0x78), AT91_SAMA5D2_CHAN_SINGLE(10, 0x78),
AT91_AT91_SAMA5D2_CHAN(11, 0x7c), AT91_SAMA5D2_CHAN_SINGLE(11, 0x7c),
AT91_SAMA5D2_CHAN_DIFF(0, 1, 0x50),
AT91_SAMA5D2_CHAN_DIFF(2, 3, 0x58),
AT91_SAMA5D2_CHAN_DIFF(4, 5, 0x60),
AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
}; };
static unsigned at91_adc_startup_time(unsigned startup_time_min, static unsigned at91_adc_startup_time(unsigned startup_time_min,
...@@ -226,7 +255,7 @@ static unsigned at91_adc_startup_time(unsigned startup_time_min, ...@@ -226,7 +255,7 @@ static unsigned at91_adc_startup_time(unsigned startup_time_min,
static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq) static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq)
{ {
struct iio_dev *indio_dev = iio_priv_to_dev(st); struct iio_dev *indio_dev = iio_priv_to_dev(st);
unsigned f_per, prescal, startup; unsigned f_per, prescal, startup, mr;
f_per = clk_get_rate(st->per_clk); f_per = clk_get_rate(st->per_clk);
prescal = (f_per / (2 * freq)) - 1; prescal = (f_per / (2 * freq)) - 1;
...@@ -234,10 +263,11 @@ static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq) ...@@ -234,10 +263,11 @@ static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq)
startup = at91_adc_startup_time(st->soc_info.startup_time, startup = at91_adc_startup_time(st->soc_info.startup_time,
freq / 1000); freq / 1000);
at91_adc_writel(st, AT91_SAMA5D2_MR, mr = at91_adc_readl(st, AT91_SAMA5D2_MR);
AT91_SAMA5D2_MR_TRANSFER(2) mr &= ~(AT91_SAMA5D2_MR_STARTUP_MASK | AT91_SAMA5D2_MR_PRESCAL_MASK);
| AT91_SAMA5D2_MR_STARTUP(startup) mr |= AT91_SAMA5D2_MR_STARTUP(startup);
| AT91_SAMA5D2_MR_PRESCAL(prescal)); mr |= AT91_SAMA5D2_MR_PRESCAL(prescal);
at91_adc_writel(st, AT91_SAMA5D2_MR, mr);
dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n", dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n",
freq, startup, prescal); freq, startup, prescal);
...@@ -278,6 +308,7 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, ...@@ -278,6 +308,7 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask) int *val, int *val2, long mask)
{ {
struct at91_adc_state *st = iio_priv(indio_dev); struct at91_adc_state *st = iio_priv(indio_dev);
u32 cor = 0;
int ret; int ret;
switch (mask) { switch (mask) {
...@@ -286,6 +317,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, ...@@ -286,6 +317,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
st->chan = chan; st->chan = chan;
if (chan->differential)
cor = (BIT(chan->channel) | BIT(chan->channel2)) <<
AT91_SAMA5D2_COR_DIFF_OFFSET;
at91_adc_writel(st, AT91_SAMA5D2_COR, cor);
at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel)); at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel));
at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel)); at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel));
at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START); at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START);
...@@ -298,6 +334,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, ...@@ -298,6 +334,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
if (ret > 0) { if (ret > 0) {
*val = st->conversion_value; *val = st->conversion_value;
if (chan->scan_type.sign == 's')
*val = sign_extend32(*val, 11);
ret = IIO_VAL_INT; ret = IIO_VAL_INT;
st->conversion_done = false; st->conversion_done = false;
} }
...@@ -310,6 +348,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, ...@@ -310,6 +348,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
*val = st->vref_uv / 1000; *val = st->vref_uv / 1000;
if (chan->differential)
*val *= 2;
*val2 = chan->scan_type.realbits; *val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2; return IIO_VAL_FRACTIONAL_LOG2;
...@@ -444,6 +484,12 @@ static int at91_adc_probe(struct platform_device *pdev) ...@@ -444,6 +484,12 @@ static int at91_adc_probe(struct platform_device *pdev)
at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST);
at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff); at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff);
/*
* Transfer field must be set to 2 according to the datasheet and
* allows different analog settings for each channel.
*/
at91_adc_writel(st, AT91_SAMA5D2_MR,
AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH);
at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate); at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate);
......
...@@ -185,9 +185,9 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev, ...@@ -185,9 +185,9 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
switch (chan->address) { switch (chan->address) {
case INA2XX_SHUNT_VOLTAGE: case INA2XX_SHUNT_VOLTAGE:
/* processed (mV) = raw*1000/shunt_div */ /* processed (mV) = raw/shunt_div */
*val2 = chip->config->shunt_div; *val2 = chip->config->shunt_div;
*val = 1000; *val = 1;
return IIO_VAL_FRACTIONAL; return IIO_VAL_FRACTIONAL;
case INA2XX_BUS_VOLTAGE: case INA2XX_BUS_VOLTAGE:
...@@ -350,6 +350,23 @@ static ssize_t ina2xx_allow_async_readout_store(struct device *dev, ...@@ -350,6 +350,23 @@ static ssize_t ina2xx_allow_async_readout_store(struct device *dev,
return len; return len;
} }
/*
* Set current LSB to 1mA, shunt is in uOhms
* (equation 13 in datasheet). We hardcode a Current_LSB
* of 1.0 x10-6. The only remaining parameter is RShunt.
* There is no need to expose the CALIBRATION register
* to the user for now. But we need to reset this register
* if the user updates RShunt after driver init, e.g upon
* reading an EEPROM/Probe-type value.
*/
static int ina2xx_set_calibration(struct ina2xx_chip_info *chip)
{
u16 regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor,
chip->shunt_resistor);
return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval);
}
static int set_shunt_resistor(struct ina2xx_chip_info *chip, unsigned int val) static int set_shunt_resistor(struct ina2xx_chip_info *chip, unsigned int val)
{ {
if (val <= 0 || val > chip->config->calibration_factor) if (val <= 0 || val > chip->config->calibration_factor)
...@@ -385,6 +402,11 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, ...@@ -385,6 +402,11 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
if (ret) if (ret)
return ret; return ret;
/* Update the Calibration register */
ret = ina2xx_set_calibration(chip);
if (ret)
return ret;
return len; return len;
} }
...@@ -602,24 +624,11 @@ static const struct iio_info ina2xx_info = { ...@@ -602,24 +624,11 @@ static const struct iio_info ina2xx_info = {
/* Initialize the configuration and calibration registers. */ /* Initialize the configuration and calibration registers. */
static int ina2xx_init(struct ina2xx_chip_info *chip, unsigned int config) static int ina2xx_init(struct ina2xx_chip_info *chip, unsigned int config)
{ {
u16 regval; int ret = regmap_write(chip->regmap, INA2XX_CONFIG, config);
int ret;
ret = regmap_write(chip->regmap, INA2XX_CONFIG, config);
if (ret) if (ret)
return ret; return ret;
/* return ina2xx_set_calibration(chip);
* Set current LSB to 1mA, shunt is in uOhms
* (equation 13 in datasheet). We hardcode a Current_LSB
* of 1.0 x10-6. The only remaining parameter is RShunt.
* There is no need to expose the CALIBRATION register
* to the user for now.
*/
regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor,
chip->shunt_resistor);
return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval);
} }
static int ina2xx_probe(struct i2c_client *client, static int ina2xx_probe(struct i2c_client *client,
......
/*
* IIO ADC driver for NXP LPC18xx ADC
*
* Copyright (C) 2016 Joachim Eastwood <manabian@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* UNSUPPORTED hardware features:
* - Hardware triggers
* - Burst mode
* - Interrupts
* - DMA
*/
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/iio/iio.h>
#include <linux/iio/driver.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
/* LPC18XX ADC registers and bits */
#define LPC18XX_ADC_CR 0x000
#define LPC18XX_ADC_CR_CLKDIV_SHIFT 8
#define LPC18XX_ADC_CR_PDN BIT(21)
#define LPC18XX_ADC_CR_START_NOW (0x1 << 24)
#define LPC18XX_ADC_GDR 0x004
/* Data register bits */
#define LPC18XX_ADC_SAMPLE_SHIFT 6
#define LPC18XX_ADC_SAMPLE_MASK 0x3ff
#define LPC18XX_ADC_CONV_DONE BIT(31)
/* Clock should be 4.5 MHz or less */
#define LPC18XX_ADC_CLK_TARGET 4500000
struct lpc18xx_adc {
struct regulator *vref;
void __iomem *base;
struct device *dev;
struct mutex lock;
struct clk *clk;
u32 cr_reg;
};
#define LPC18XX_ADC_CHAN(_idx) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = _idx, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
static const struct iio_chan_spec lpc18xx_adc_iio_channels[] = {
LPC18XX_ADC_CHAN(0),
LPC18XX_ADC_CHAN(1),
LPC18XX_ADC_CHAN(2),
LPC18XX_ADC_CHAN(3),
LPC18XX_ADC_CHAN(4),
LPC18XX_ADC_CHAN(5),
LPC18XX_ADC_CHAN(6),
LPC18XX_ADC_CHAN(7),
};
static int lpc18xx_adc_read_chan(struct lpc18xx_adc *adc, unsigned int ch)
{
int ret;
u32 reg;
reg = adc->cr_reg | BIT(ch) | LPC18XX_ADC_CR_START_NOW;
writel(reg, adc->base + LPC18XX_ADC_CR);
ret = readl_poll_timeout(adc->base + LPC18XX_ADC_GDR, reg,
reg & LPC18XX_ADC_CONV_DONE, 3, 9);
if (ret) {
dev_warn(adc->dev, "adc read timed out\n");
return ret;
}
return (reg >> LPC18XX_ADC_SAMPLE_SHIFT) & LPC18XX_ADC_SAMPLE_MASK;
}
static int lpc18xx_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct lpc18xx_adc *adc = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&adc->lock);
*val = lpc18xx_adc_read_chan(adc, chan->channel);
mutex_unlock(&adc->lock);
if (*val < 0)
return *val;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = regulator_get_voltage(adc->vref) / 1000;
*val2 = 10;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
static const struct iio_info lpc18xx_adc_info = {
.read_raw = lpc18xx_adc_read_raw,
.driver_module = THIS_MODULE,
};
static int lpc18xx_adc_probe(struct platform_device *pdev)
{
struct iio_dev *indio_dev;
struct lpc18xx_adc *adc;
struct resource *res;
unsigned int clkdiv;
unsigned long rate;
int ret;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
if (!indio_dev)
return -ENOMEM;
platform_set_drvdata(pdev, indio_dev);
adc = iio_priv(indio_dev);
adc->dev = &pdev->dev;
mutex_init(&adc->lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
adc->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(adc->base))
return PTR_ERR(adc->base);
adc->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(adc->clk)) {
dev_err(&pdev->dev, "error getting clock\n");
return PTR_ERR(adc->clk);
}
rate = clk_get_rate(adc->clk);
clkdiv = DIV_ROUND_UP(rate, LPC18XX_ADC_CLK_TARGET);
adc->vref = devm_regulator_get(&pdev->dev, "vref");
if (IS_ERR(adc->vref)) {
dev_err(&pdev->dev, "error getting regulator\n");
return PTR_ERR(adc->vref);
}
indio_dev->name = dev_name(&pdev->dev);
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &lpc18xx_adc_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = lpc18xx_adc_iio_channels;
indio_dev->num_channels = ARRAY_SIZE(lpc18xx_adc_iio_channels);
ret = regulator_enable(adc->vref);
if (ret) {
dev_err(&pdev->dev, "unable to enable regulator\n");
return ret;
}
ret = clk_prepare_enable(adc->clk);
if (ret) {
dev_err(&pdev->dev, "unable to enable clock\n");
goto dis_reg;
}
adc->cr_reg = (clkdiv << LPC18XX_ADC_CR_CLKDIV_SHIFT) |
LPC18XX_ADC_CR_PDN;
writel(adc->cr_reg, adc->base + LPC18XX_ADC_CR);
ret = iio_device_register(indio_dev);
if (ret) {
dev_err(&pdev->dev, "unable to register device\n");
goto dis_clk;
}
return 0;
dis_clk:
writel(0, adc->base + LPC18XX_ADC_CR);
clk_disable_unprepare(adc->clk);
dis_reg:
regulator_disable(adc->vref);
return ret;
}
static int lpc18xx_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct lpc18xx_adc *adc = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
writel(0, adc->base + LPC18XX_ADC_CR);
clk_disable_unprepare(adc->clk);
regulator_disable(adc->vref);
return 0;
}
static const struct of_device_id lpc18xx_adc_match[] = {
{ .compatible = "nxp,lpc1850-adc" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, lpc18xx_adc_match);
static struct platform_driver lpc18xx_adc_driver = {
.probe = lpc18xx_adc_probe,
.remove = lpc18xx_adc_remove,
.driver = {
.name = "lpc18xx-adc",
.of_match_table = lpc18xx_adc_match,
},
};
module_platform_driver(lpc18xx_adc_driver);
MODULE_DESCRIPTION("LPC18xx ADC driver");
MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
MODULE_LICENSE("GPL v2");
...@@ -159,6 +159,22 @@ static const struct rockchip_saradc_data rk3066_tsadc_data = { ...@@ -159,6 +159,22 @@ static const struct rockchip_saradc_data rk3066_tsadc_data = {
.clk_rate = 50000, .clk_rate = 50000,
}; };
static const struct iio_chan_spec rockchip_rk3399_saradc_iio_channels[] = {
ADC_CHANNEL(0, "adc0"),
ADC_CHANNEL(1, "adc1"),
ADC_CHANNEL(2, "adc2"),
ADC_CHANNEL(3, "adc3"),
ADC_CHANNEL(4, "adc4"),
ADC_CHANNEL(5, "adc5"),
};
static const struct rockchip_saradc_data rk3399_saradc_data = {
.num_bits = 10,
.channels = rockchip_rk3399_saradc_iio_channels,
.num_channels = ARRAY_SIZE(rockchip_rk3399_saradc_iio_channels),
.clk_rate = 1000000,
};
static const struct of_device_id rockchip_saradc_match[] = { static const struct of_device_id rockchip_saradc_match[] = {
{ {
.compatible = "rockchip,saradc", .compatible = "rockchip,saradc",
...@@ -166,6 +182,9 @@ static const struct of_device_id rockchip_saradc_match[] = { ...@@ -166,6 +182,9 @@ static const struct of_device_id rockchip_saradc_match[] = {
}, { }, {
.compatible = "rockchip,rk3066-tsadc", .compatible = "rockchip,rk3066-tsadc",
.data = &rk3066_tsadc_data, .data = &rk3066_tsadc_data,
}, {
.compatible = "rockchip,rk3399-saradc",
.data = &rk3399_saradc_data,
}, },
{}, {},
}; };
......
...@@ -24,19 +24,13 @@ ...@@ -24,19 +24,13 @@
int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
{ {
u8 *addr; u8 addr[3]; /* no ST sensor has more than 3 channels */
int i, n = 0, len; int i, n = 0, len;
struct st_sensor_data *sdata = iio_priv(indio_dev); struct st_sensor_data *sdata = iio_priv(indio_dev);
unsigned int num_data_channels = sdata->num_data_channels; unsigned int num_data_channels = sdata->num_data_channels;
unsigned int byte_for_channel = unsigned int byte_for_channel =
indio_dev->channels[0].scan_type.storagebits >> 3; indio_dev->channels[0].scan_type.storagebits >> 3;
addr = kmalloc(num_data_channels, GFP_KERNEL);
if (!addr) {
len = -ENOMEM;
goto st_sensors_get_buffer_element_error;
}
for (i = 0; i < num_data_channels; i++) { for (i = 0; i < num_data_channels; i++) {
if (test_bit(i, indio_dev->active_scan_mask)) { if (test_bit(i, indio_dev->active_scan_mask)) {
addr[n] = indio_dev->channels[i].address; addr[n] = indio_dev->channels[i].address;
...@@ -57,10 +51,8 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) ...@@ -57,10 +51,8 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
u8 *rx_array; u8 *rx_array;
rx_array = kmalloc(byte_for_channel * num_data_channels, rx_array = kmalloc(byte_for_channel * num_data_channels,
GFP_KERNEL); GFP_KERNEL);
if (!rx_array) { if (!rx_array)
len = -ENOMEM; return -ENOMEM;
goto st_sensors_free_memory;
}
len = sdata->tf->read_multiple_byte(&sdata->tb, len = sdata->tf->read_multiple_byte(&sdata->tb,
sdata->dev, addr[0], sdata->dev, addr[0],
...@@ -68,7 +60,7 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) ...@@ -68,7 +60,7 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
rx_array, sdata->multiread_bit); rx_array, sdata->multiread_bit);
if (len < 0) { if (len < 0) {
kfree(rx_array); kfree(rx_array);
goto st_sensors_free_memory; return len;
} }
for (i = 0; i < n * byte_for_channel; i++) { for (i = 0; i < n * byte_for_channel; i++) {
...@@ -87,17 +79,11 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) ...@@ -87,17 +79,11 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
buf, sdata->multiread_bit); buf, sdata->multiread_bit);
break; break;
default: default:
len = -EINVAL; return -EINVAL;
goto st_sensors_free_memory;
}
if (len != byte_for_channel * n) {
len = -EIO;
goto st_sensors_free_memory;
} }
if (len != byte_for_channel * n)
return -EIO;
st_sensors_free_memory:
kfree(addr);
st_sensors_get_buffer_element_error:
return len; return len;
} }
EXPORT_SYMBOL(st_sensors_get_buffer_element); EXPORT_SYMBOL(st_sensors_get_buffer_element);
......
...@@ -154,6 +154,16 @@ config AD7303 ...@@ -154,6 +154,16 @@ config AD7303
To compile this driver as module choose M here: the module will be called To compile this driver as module choose M here: the module will be called
ad7303. ad7303.
config LPC18XX_DAC
tristate "NXP LPC18xx DAC driver"
depends on ARCH_LPC18XX || COMPILE_TEST
depends on OF && HAS_IOMEM
help
Say yes here to build support for NXP LPC18XX DAC.
To compile this driver as a module, choose M here: the module will be
called lpc18xx_dac.
config M62332 config M62332
tristate "Mitsubishi M62332 DAC driver" tristate "Mitsubishi M62332 DAC driver"
depends on I2C depends on I2C
......
...@@ -17,6 +17,7 @@ obj-$(CONFIG_AD5764) += ad5764.o ...@@ -17,6 +17,7 @@ obj-$(CONFIG_AD5764) += ad5764.o
obj-$(CONFIG_AD5791) += ad5791.o obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_AD7303) += ad7303.o obj-$(CONFIG_AD7303) += ad7303.o
obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o
obj-$(CONFIG_M62332) += m62332.o obj-$(CONFIG_M62332) += m62332.o
obj-$(CONFIG_MAX517) += max517.o obj-$(CONFIG_MAX517) += max517.o
obj-$(CONFIG_MAX5821) += max5821.o obj-$(CONFIG_MAX5821) += max5821.o
......
/*
* IIO DAC driver for NXP LPC18xx DAC
*
* Copyright (C) 2016 Joachim Eastwood <manabian@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* UNSUPPORTED hardware features:
* - Interrupts
* - DMA
*/
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/iio/iio.h>
#include <linux/iio/driver.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
/* LPC18XX DAC registers and bits */
#define LPC18XX_DAC_CR 0x000
#define LPC18XX_DAC_CR_VALUE_SHIFT 6
#define LPC18XX_DAC_CR_VALUE_MASK 0x3ff
#define LPC18XX_DAC_CR_BIAS BIT(16)
#define LPC18XX_DAC_CTRL 0x004
#define LPC18XX_DAC_CTRL_DMA_ENA BIT(3)
struct lpc18xx_dac {
struct regulator *vref;
void __iomem *base;
struct mutex lock;
struct clk *clk;
};
static const struct iio_chan_spec lpc18xx_dac_iio_channels[] = {
{
.type = IIO_VOLTAGE,
.output = 1,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
},
};
static int lpc18xx_dac_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct lpc18xx_dac *dac = iio_priv(indio_dev);
u32 reg;
switch (mask) {
case IIO_CHAN_INFO_RAW:
reg = readl(dac->base + LPC18XX_DAC_CR);
*val = reg >> LPC18XX_DAC_CR_VALUE_SHIFT;
*val &= LPC18XX_DAC_CR_VALUE_MASK;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = regulator_get_voltage(dac->vref) / 1000;
*val2 = 10;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
static int lpc18xx_dac_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct lpc18xx_dac *dac = iio_priv(indio_dev);
u32 reg;
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (val < 0 || val > LPC18XX_DAC_CR_VALUE_MASK)
return -EINVAL;
reg = LPC18XX_DAC_CR_BIAS;
reg |= val << LPC18XX_DAC_CR_VALUE_SHIFT;
mutex_lock(&dac->lock);
writel(reg, dac->base + LPC18XX_DAC_CR);
writel(LPC18XX_DAC_CTRL_DMA_ENA, dac->base + LPC18XX_DAC_CTRL);
mutex_unlock(&dac->lock);
return 0;
}
return -EINVAL;
}
static const struct iio_info lpc18xx_dac_info = {
.read_raw = lpc18xx_dac_read_raw,
.write_raw = lpc18xx_dac_write_raw,
.driver_module = THIS_MODULE,
};
static int lpc18xx_dac_probe(struct platform_device *pdev)
{
struct iio_dev *indio_dev;
struct lpc18xx_dac *dac;
struct resource *res;
int ret;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*dac));
if (!indio_dev)
return -ENOMEM;
platform_set_drvdata(pdev, indio_dev);
dac = iio_priv(indio_dev);
mutex_init(&dac->lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dac->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dac->base))
return PTR_ERR(dac->base);
dac->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(dac->clk)) {
dev_err(&pdev->dev, "error getting clock\n");
return PTR_ERR(dac->clk);
}
dac->vref = devm_regulator_get(&pdev->dev, "vref");
if (IS_ERR(dac->vref)) {
dev_err(&pdev->dev, "error getting regulator\n");
return PTR_ERR(dac->vref);
}
indio_dev->name = dev_name(&pdev->dev);
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &lpc18xx_dac_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = lpc18xx_dac_iio_channels;
indio_dev->num_channels = ARRAY_SIZE(lpc18xx_dac_iio_channels);
ret = regulator_enable(dac->vref);
if (ret) {
dev_err(&pdev->dev, "unable to enable regulator\n");
return ret;
}
ret = clk_prepare_enable(dac->clk);
if (ret) {
dev_err(&pdev->dev, "unable to enable clock\n");
goto dis_reg;
}
writel(0, dac->base + LPC18XX_DAC_CTRL);
writel(0, dac->base + LPC18XX_DAC_CR);
ret = iio_device_register(indio_dev);
if (ret) {
dev_err(&pdev->dev, "unable to register device\n");
goto dis_clk;
}
return 0;
dis_clk:
clk_disable_unprepare(dac->clk);
dis_reg:
regulator_disable(dac->vref);
return ret;
}
static int lpc18xx_dac_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct lpc18xx_dac *dac = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
writel(0, dac->base + LPC18XX_DAC_CTRL);
clk_disable_unprepare(dac->clk);
regulator_disable(dac->vref);
return 0;
}
static const struct of_device_id lpc18xx_dac_match[] = {
{ .compatible = "nxp,lpc1850-dac" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, lpc18xx_dac_match);
static struct platform_driver lpc18xx_dac_driver = {
.probe = lpc18xx_dac_probe,
.remove = lpc18xx_dac_remove,
.driver = {
.name = "lpc18xx-dac",
.of_match_table = lpc18xx_dac_match,
},
};
module_platform_driver(lpc18xx_dac_driver);
MODULE_DESCRIPTION("LPC18xx DAC driver");
MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
MODULE_LICENSE("GPL v2");
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
...@@ -31,7 +30,6 @@ ...@@ -31,7 +30,6 @@
#include "bmg160.h" #include "bmg160.h"
#define BMG160_IRQ_NAME "bmg160_event" #define BMG160_IRQ_NAME "bmg160_event"
#define BMG160_GPIO_NAME "gpio_int"
#define BMG160_REG_CHIP_ID 0x00 #define BMG160_REG_CHIP_ID 0x00
#define BMG160_CHIP_ID_VAL 0x0F #define BMG160_CHIP_ID_VAL 0x0F
...@@ -116,6 +114,7 @@ enum bmg160_axis { ...@@ -116,6 +114,7 @@ enum bmg160_axis {
AXIS_X, AXIS_X,
AXIS_Y, AXIS_Y,
AXIS_Z, AXIS_Z,
AXIS_MAX,
}; };
static const struct { static const struct {
...@@ -733,6 +732,7 @@ static const struct iio_event_spec bmg160_event = { ...@@ -733,6 +732,7 @@ static const struct iio_event_spec bmg160_event = {
.sign = 's', \ .sign = 's', \
.realbits = 16, \ .realbits = 16, \
.storagebits = 16, \ .storagebits = 16, \
.endianness = IIO_LE, \
}, \ }, \
.event_spec = &bmg160_event, \ .event_spec = &bmg160_event, \
.num_event_specs = 1 \ .num_event_specs = 1 \
...@@ -763,26 +763,23 @@ static const struct iio_info bmg160_info = { ...@@ -763,26 +763,23 @@ static const struct iio_info bmg160_info = {
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
}; };
static const unsigned long bmg160_accel_scan_masks[] = {
BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
0};
static irqreturn_t bmg160_trigger_handler(int irq, void *p) static irqreturn_t bmg160_trigger_handler(int irq, void *p)
{ {
struct iio_poll_func *pf = p; struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev; struct iio_dev *indio_dev = pf->indio_dev;
struct bmg160_data *data = iio_priv(indio_dev); struct bmg160_data *data = iio_priv(indio_dev);
int bit, ret, i = 0; int ret;
unsigned int val;
mutex_lock(&data->mutex); mutex_lock(&data->mutex);
for_each_set_bit(bit, indio_dev->active_scan_mask, ret = regmap_bulk_read(data->regmap, BMG160_REG_XOUT_L,
indio_dev->masklength) { data->buffer, AXIS_MAX * 2);
ret = regmap_bulk_read(data->regmap, BMG160_AXIS_TO_REG(bit),
&val, 2);
if (ret < 0) {
mutex_unlock(&data->mutex);
goto err;
}
data->buffer[i++] = ret;
}
mutex_unlock(&data->mutex); mutex_unlock(&data->mutex);
if (ret < 0)
goto err;
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
pf->timestamp); pf->timestamp);
...@@ -955,29 +952,6 @@ static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = { ...@@ -955,29 +952,6 @@ static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = {
.postdisable = bmg160_buffer_postdisable, .postdisable = bmg160_buffer_postdisable,
}; };
static int bmg160_gpio_probe(struct bmg160_data *data)
{
struct device *dev;
struct gpio_desc *gpio;
dev = data->dev;
/* data ready gpio interrupt pin */
gpio = devm_gpiod_get_index(dev, BMG160_GPIO_NAME, 0, GPIOD_IN);
if (IS_ERR(gpio)) {
dev_err(dev, "acpi gpio get index failed\n");
return PTR_ERR(gpio);
}
data->irq = gpiod_to_irq(gpio);
dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio),
data->irq);
return 0;
}
static const char *bmg160_match_acpi_device(struct device *dev) static const char *bmg160_match_acpi_device(struct device *dev)
{ {
const struct acpi_device_id *id; const struct acpi_device_id *id;
...@@ -1019,12 +993,10 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, ...@@ -1019,12 +993,10 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
indio_dev->channels = bmg160_channels; indio_dev->channels = bmg160_channels;
indio_dev->num_channels = ARRAY_SIZE(bmg160_channels); indio_dev->num_channels = ARRAY_SIZE(bmg160_channels);
indio_dev->name = name; indio_dev->name = name;
indio_dev->available_scan_masks = bmg160_accel_scan_masks;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &bmg160_info; indio_dev->info = &bmg160_info;
if (data->irq <= 0)
bmg160_gpio_probe(data);
if (data->irq > 0) { if (data->irq > 0) {
ret = devm_request_threaded_irq(dev, ret = devm_request_threaded_irq(dev,
data->irq, data->irq,
......
...@@ -104,6 +104,19 @@ static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap, ...@@ -104,6 +104,19 @@ static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
return 0; return 0;
} }
static const char *inv_mpu_match_acpi_device(struct device *dev, int *chip_id)
{
const struct acpi_device_id *id;
id = acpi_match_device(dev->driver->acpi_match_table, dev);
if (!id)
return NULL;
*chip_id = (int)id->driver_data;
return dev_name(dev);
}
/** /**
* inv_mpu_probe() - probe function. * inv_mpu_probe() - probe function.
* @client: i2c client. * @client: i2c client.
...@@ -115,14 +128,25 @@ static int inv_mpu_probe(struct i2c_client *client, ...@@ -115,14 +128,25 @@ static int inv_mpu_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct inv_mpu6050_state *st; struct inv_mpu6050_state *st;
int result; int result, chip_type;
const char *name = id ? id->name : NULL;
struct regmap *regmap; struct regmap *regmap;
const char *name;
if (!i2c_check_functionality(client->adapter, if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_I2C_BLOCK)) I2C_FUNC_SMBUS_I2C_BLOCK))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (id) {
chip_type = (int)id->driver_data;
name = id->name;
} else if (ACPI_HANDLE(&client->dev)) {
name = inv_mpu_match_acpi_device(&client->dev, &chip_type);
if (!name)
return -ENODEV;
} else {
return -ENOSYS;
}
regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config); regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config);
if (IS_ERR(regmap)) { if (IS_ERR(regmap)) {
dev_err(&client->dev, "Failed to register i2c regmap %d\n", dev_err(&client->dev, "Failed to register i2c regmap %d\n",
...@@ -131,7 +155,7 @@ static int inv_mpu_probe(struct i2c_client *client, ...@@ -131,7 +155,7 @@ static int inv_mpu_probe(struct i2c_client *client,
} }
result = inv_mpu_core_probe(regmap, client->irq, name, result = inv_mpu_core_probe(regmap, client->irq, name,
NULL, id->driver_data); NULL, chip_type);
if (result < 0) if (result < 0)
return result; return result;
......
...@@ -46,6 +46,7 @@ static int inv_mpu_probe(struct spi_device *spi) ...@@ -46,6 +46,7 @@ static int inv_mpu_probe(struct spi_device *spi)
struct regmap *regmap; struct regmap *regmap;
const struct spi_device_id *id = spi_get_device_id(spi); const struct spi_device_id *id = spi_get_device_id(spi);
const char *name = id ? id->name : NULL; const char *name = id ? id->name : NULL;
const int chip_type = id ? id->driver_data : 0;
regmap = devm_regmap_init_spi(spi, &inv_mpu_regmap_config); regmap = devm_regmap_init_spi(spi, &inv_mpu_regmap_config);
if (IS_ERR(regmap)) { if (IS_ERR(regmap)) {
...@@ -55,7 +56,7 @@ static int inv_mpu_probe(struct spi_device *spi) ...@@ -55,7 +56,7 @@ static int inv_mpu_probe(struct spi_device *spi)
} }
return inv_mpu_core_probe(regmap, spi->irq, name, return inv_mpu_core_probe(regmap, spi->irq, name,
inv_mpu_i2c_disable, id->driver_data); inv_mpu_i2c_disable, chip_type);
} }
static int inv_mpu_remove(struct spi_device *spi) static int inv_mpu_remove(struct spi_device *spi)
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/anon_inodes.h> #include <linux/anon_inodes.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/mutex.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include "iio_core.h" #include "iio_core.h"
#include "iio_core_trigger.h" #include "iio_core_trigger.h"
...@@ -78,6 +79,7 @@ static const char * const iio_chan_type_name_spec[] = { ...@@ -78,6 +79,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_CONCENTRATION] = "concentration", [IIO_CONCENTRATION] = "concentration",
[IIO_RESISTANCE] = "resistance", [IIO_RESISTANCE] = "resistance",
[IIO_PH] = "ph", [IIO_PH] = "ph",
[IIO_UVINDEX] = "uvindex",
}; };
static const char * const iio_modifier_names[] = { static const char * const iio_modifier_names[] = {
...@@ -100,6 +102,7 @@ static const char * const iio_modifier_names[] = { ...@@ -100,6 +102,7 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_LIGHT_RED] = "red", [IIO_MOD_LIGHT_RED] = "red",
[IIO_MOD_LIGHT_GREEN] = "green", [IIO_MOD_LIGHT_GREEN] = "green",
[IIO_MOD_LIGHT_BLUE] = "blue", [IIO_MOD_LIGHT_BLUE] = "blue",
[IIO_MOD_LIGHT_UV] = "uv",
[IIO_MOD_QUATERNION] = "quaternion", [IIO_MOD_QUATERNION] = "quaternion",
[IIO_MOD_TEMP_AMBIENT] = "ambient", [IIO_MOD_TEMP_AMBIENT] = "ambient",
[IIO_MOD_TEMP_OBJECT] = "object", [IIO_MOD_TEMP_OBJECT] = "object",
...@@ -1375,6 +1378,44 @@ void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev) ...@@ -1375,6 +1378,44 @@ void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev)
} }
EXPORT_SYMBOL_GPL(devm_iio_device_unregister); EXPORT_SYMBOL_GPL(devm_iio_device_unregister);
/**
* iio_device_claim_direct_mode - Keep device in direct mode
* @indio_dev: the iio_dev associated with the device
*
* If the device is in direct mode it is guaranteed to stay
* that way until iio_device_release_direct_mode() is called.
*
* Use with iio_device_release_direct_mode()
*
* Returns: 0 on success, -EBUSY on failure
*/
int iio_device_claim_direct_mode(struct iio_dev *indio_dev)
{
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev)) {
mutex_unlock(&indio_dev->mlock);
return -EBUSY;
}
return 0;
}
EXPORT_SYMBOL_GPL(iio_device_claim_direct_mode);
/**
* iio_device_release_direct_mode - releases claim on direct mode
* @indio_dev: the iio_dev associated with the device
*
* Release the claim. Device is no longer guaranteed to stay
* in direct mode.
*
* Use with iio_device_claim_direct_mode()
*/
void iio_device_release_direct_mode(struct iio_dev *indio_dev)
{
mutex_unlock(&indio_dev->mlock);
}
EXPORT_SYMBOL_GPL(iio_device_release_direct_mode);
subsys_initcall(iio_init); subsys_initcall(iio_init);
module_exit(iio_exit); module_exit(iio_exit);
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/gpio/consumer.h>
#include <linux/iio/events.h> #include <linux/iio/events.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
......
...@@ -806,8 +806,7 @@ static int tsl2563_probe(struct i2c_client *client, ...@@ -806,8 +806,7 @@ static int tsl2563_probe(struct i2c_client *client,
return 0; return 0;
fail: fail:
cancel_delayed_work(&chip->poweroff_work); cancel_delayed_work_sync(&chip->poweroff_work);
flush_scheduled_work();
return err; return err;
} }
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
...@@ -361,7 +362,6 @@ static const struct ak_def ak_def_array[AK_MAX_TYPE] = { ...@@ -361,7 +362,6 @@ static const struct ak_def ak_def_array[AK_MAX_TYPE] = {
struct ak8975_data { struct ak8975_data {
struct i2c_client *client; struct i2c_client *client;
const struct ak_def *def; const struct ak_def *def;
struct attribute_group attrs;
struct mutex lock; struct mutex lock;
u8 asa[3]; u8 asa[3];
long raw_to_gauss[3]; long raw_to_gauss[3];
...@@ -370,8 +370,40 @@ struct ak8975_data { ...@@ -370,8 +370,40 @@ struct ak8975_data {
wait_queue_head_t data_ready_queue; wait_queue_head_t data_ready_queue;
unsigned long flags; unsigned long flags;
u8 cntl_cache; u8 cntl_cache;
struct regulator *vdd;
}; };
/* Enable attached power regulator if any. */
static int ak8975_power_on(struct i2c_client *client)
{
const struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct ak8975_data *data = iio_priv(indio_dev);
int ret;
data->vdd = devm_regulator_get(&client->dev, "vdd");
if (IS_ERR_OR_NULL(data->vdd)) {
ret = PTR_ERR(data->vdd);
if (ret == -ENODEV)
ret = 0;
} else {
ret = regulator_enable(data->vdd);
}
if (ret)
dev_err(&client->dev, "failed to enable Vdd supply: %d\n", ret);
return ret;
}
/* Disable attached power regulator if any. */
static void ak8975_power_off(const struct i2c_client *client)
{
const struct iio_dev *indio_dev = i2c_get_clientdata(client);
const struct ak8975_data *data = iio_priv(indio_dev);
if (!IS_ERR_OR_NULL(data->vdd))
regulator_disable(data->vdd);
}
/* /*
* Return 0 if the i2c device is the one we expect. * Return 0 if the i2c device is the one we expect.
* return a negative error number otherwise * return a negative error number otherwise
...@@ -774,8 +806,11 @@ static int ak8975_probe(struct i2c_client *client, ...@@ -774,8 +806,11 @@ static int ak8975_probe(struct i2c_client *client,
if (id) { if (id) {
chipset = (enum asahi_compass_chipset)(id->driver_data); chipset = (enum asahi_compass_chipset)(id->driver_data);
name = id->name; name = id->name;
} else if (ACPI_HANDLE(&client->dev)) } else if (ACPI_HANDLE(&client->dev)) {
name = ak8975_match_acpi_device(&client->dev, &chipset); name = ak8975_match_acpi_device(&client->dev, &chipset);
if (!name)
return -ENODEV;
}
else else
return -ENOSYS; return -ENOSYS;
...@@ -786,10 +821,15 @@ static int ak8975_probe(struct i2c_client *client, ...@@ -786,10 +821,15 @@ static int ak8975_probe(struct i2c_client *client,
} }
data->def = &ak_def_array[chipset]; data->def = &ak_def_array[chipset];
err = ak8975_power_on(client);
if (err)
return err;
err = ak8975_who_i_am(client, data->def->type); err = ak8975_who_i_am(client, data->def->type);
if (err < 0) { if (err < 0) {
dev_err(&client->dev, "Unexpected device\n"); dev_err(&client->dev, "Unexpected device\n");
return err; goto power_off;
} }
dev_dbg(&client->dev, "Asahi compass chip %s\n", name); dev_dbg(&client->dev, "Asahi compass chip %s\n", name);
...@@ -797,7 +837,7 @@ static int ak8975_probe(struct i2c_client *client, ...@@ -797,7 +837,7 @@ static int ak8975_probe(struct i2c_client *client,
err = ak8975_setup(client); err = ak8975_setup(client);
if (err < 0) { if (err < 0) {
dev_err(&client->dev, "%s initialization fails\n", name); dev_err(&client->dev, "%s initialization fails\n", name);
return err; goto power_off;
} }
mutex_init(&data->lock); mutex_init(&data->lock);
...@@ -807,7 +847,26 @@ static int ak8975_probe(struct i2c_client *client, ...@@ -807,7 +847,26 @@ static int ak8975_probe(struct i2c_client *client,
indio_dev->info = &ak8975_info; indio_dev->info = &ak8975_info;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->name = name; indio_dev->name = name;
return devm_iio_device_register(&client->dev, indio_dev);
err = iio_device_register(indio_dev);
if (err)
goto power_off;
return 0;
power_off:
ak8975_power_off(client);
return err;
}
static int ak8975_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
ak8975_power_off(client);
return 0;
} }
static const struct i2c_device_id ak8975_id[] = { static const struct i2c_device_id ak8975_id[] = {
...@@ -841,6 +900,7 @@ static struct i2c_driver ak8975_driver = { ...@@ -841,6 +900,7 @@ static struct i2c_driver ak8975_driver = {
.acpi_match_table = ACPI_PTR(ak_acpi_match), .acpi_match_table = ACPI_PTR(ak_acpi_match),
}, },
.probe = ak8975_probe, .probe = ak8975_probe,
.remove = ak8975_remove,
.id_table = ak8975_id, .id_table = ak8975_id,
}; };
module_i2c_driver(ak8975_driver); module_i2c_driver(ak8975_driver);
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
......
...@@ -5,6 +5,24 @@ ...@@ -5,6 +5,24 @@
menu "Digital potentiometers" menu "Digital potentiometers"
config MCP4131
tristate "Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer driver"
depends on SPI
help
Say yes here to build support for the Microchip
MCP4131, MCP4132,
MCP4141, MCP4142,
MCP4151, MCP4152,
MCP4161, MCP4162,
MCP4231, MCP4232,
MCP4241, MCP4242,
MCP4251, MCP4252,
MCP4261, MCP4262,
digital potentiomenter chips.
To compile this driver as a module, choose M here: the
module will be called mcp4131.
config MCP4531 config MCP4531
tristate "Microchip MCP45xx/MCP46xx Digital Potentiometer driver" tristate "Microchip MCP45xx/MCP46xx Digital Potentiometer driver"
depends on I2C depends on I2C
......
...@@ -3,5 +3,6 @@ ...@@ -3,5 +3,6 @@
# #
# When adding new entries keep the list in alphabetical order # When adding new entries keep the list in alphabetical order
obj-$(CONFIG_MCP4131) += mcp4131.o
obj-$(CONFIG_MCP4531) += mcp4531.o obj-$(CONFIG_MCP4531) += mcp4531.o
obj-$(CONFIG_TPL0102) += tpl0102.o obj-$(CONFIG_TPL0102) += tpl0102.o
This diff is collapsed.
...@@ -79,7 +79,7 @@ static const struct mcp4531_cfg mcp4531_cfg[] = { ...@@ -79,7 +79,7 @@ static const struct mcp4531_cfg mcp4531_cfg[] = {
struct mcp4531_data { struct mcp4531_data {
struct i2c_client *client; struct i2c_client *client;
unsigned long devid; const struct mcp4531_cfg *cfg;
}; };
#define MCP4531_CHANNEL(ch) { \ #define MCP4531_CHANNEL(ch) { \
...@@ -113,8 +113,8 @@ static int mcp4531_read_raw(struct iio_dev *indio_dev, ...@@ -113,8 +113,8 @@ static int mcp4531_read_raw(struct iio_dev *indio_dev,
*val = ret; *val = ret;
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
*val = 1000 * mcp4531_cfg[data->devid].kohms; *val = 1000 * data->cfg->kohms;
*val2 = mcp4531_cfg[data->devid].max_pos; *val2 = data->cfg->max_pos;
return IIO_VAL_FRACTIONAL; return IIO_VAL_FRACTIONAL;
} }
...@@ -130,7 +130,7 @@ static int mcp4531_write_raw(struct iio_dev *indio_dev, ...@@ -130,7 +130,7 @@ static int mcp4531_write_raw(struct iio_dev *indio_dev,
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
if (val > mcp4531_cfg[data->devid].max_pos || val < 0) if (val > data->cfg->max_pos || val < 0)
return -EINVAL; return -EINVAL;
break; break;
default: default:
...@@ -152,7 +152,6 @@ static int mcp4531_probe(struct i2c_client *client, ...@@ -152,7 +152,6 @@ static int mcp4531_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
unsigned long devid = id->driver_data;
struct mcp4531_data *data; struct mcp4531_data *data;
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
...@@ -168,12 +167,12 @@ static int mcp4531_probe(struct i2c_client *client, ...@@ -168,12 +167,12 @@ static int mcp4531_probe(struct i2c_client *client,
data = iio_priv(indio_dev); data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev); i2c_set_clientdata(client, indio_dev);
data->client = client; data->client = client;
data->devid = devid; data->cfg = &mcp4531_cfg[id->driver_data];
indio_dev->dev.parent = dev; indio_dev->dev.parent = dev;
indio_dev->info = &mcp4531_info; indio_dev->info = &mcp4531_info;
indio_dev->channels = mcp4531_channels; indio_dev->channels = mcp4531_channels;
indio_dev->num_channels = mcp4531_cfg[devid].wipers; indio_dev->num_channels = data->cfg->wipers;
indio_dev->name = client->name; indio_dev->name = client->name;
return devm_iio_device_register(dev, indio_dev); return devm_iio_device_register(dev, indio_dev);
......
...@@ -118,7 +118,7 @@ static int tpl0102_probe(struct i2c_client *client, ...@@ -118,7 +118,7 @@ static int tpl0102_probe(struct i2c_client *client,
if (!i2c_check_functionality(client->adapter, if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_WORD_DATA)) I2C_FUNC_SMBUS_WORD_DATA))
return -ENOTSUPP; return -EOPNOTSUPP;
indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
if (!indio_dev) if (!indio_dev)
......
...@@ -148,4 +148,14 @@ config T5403 ...@@ -148,4 +148,14 @@ config T5403
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called t5403. will be called t5403.
config HP206C
tristate "HOPERF HP206C precision barometer and altimeter sensor"
depends on I2C
help
Say yes here to build support for the HOPREF HP206C precision
barometer and altimeter sensor.
This driver can also be built as a module. If so, the module will
be called hp206c.
endmenu endmenu
...@@ -17,6 +17,7 @@ obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o ...@@ -17,6 +17,7 @@ obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o
st_pressure-y := st_pressure_core.o st_pressure-y := st_pressure_core.o
st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o
obj-$(CONFIG_T5403) += t5403.o obj-$(CONFIG_T5403) += t5403.o
obj-$(CONFIG_HP206C) += hp206c.o
obj-$(CONFIG_IIO_ST_PRESS_I2C) += st_pressure_i2c.o obj-$(CONFIG_IIO_ST_PRESS_I2C) += st_pressure_i2c.o
obj-$(CONFIG_IIO_ST_PRESS_SPI) += st_pressure_spi.o obj-$(CONFIG_IIO_ST_PRESS_SPI) += st_pressure_spi.o
This diff is collapsed.
...@@ -16,15 +16,11 @@ ...@@ -16,15 +16,11 @@
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/mutex.h> #include <linux/mutex.h>
struct regulator;
#define MS5611_RESET 0x1e #define MS5611_RESET 0x1e
#define MS5611_READ_ADC 0x00 #define MS5611_READ_ADC 0x00
#define MS5611_READ_PROM_WORD 0xA0 #define MS5611_READ_PROM_WORD 0xA0
#define MS5611_START_TEMP_CONV 0x58
#define MS5611_START_PRESSURE_CONV 0x48
#define MS5611_CONV_TIME_MIN 9040
#define MS5611_CONV_TIME_MAX 10000
#define MS5611_PROM_WORDS_NB 8 #define MS5611_PROM_WORDS_NB 8
enum { enum {
...@@ -39,16 +35,31 @@ struct ms5611_chip_info { ...@@ -39,16 +35,31 @@ struct ms5611_chip_info {
s32 *temp, s32 *pressure); s32 *temp, s32 *pressure);
}; };
/*
* OverSampling Rate descriptor.
* Warning: cmd MUST be kept aligned on a word boundary (see
* m5611_spi_read_adc_temp_and_pressure in ms5611_spi.c).
*/
struct ms5611_osr {
unsigned long conv_usec;
u8 cmd;
unsigned short rate;
};
struct ms5611_state { struct ms5611_state {
void *client; void *client;
struct mutex lock; struct mutex lock;
const struct ms5611_osr *pressure_osr;
const struct ms5611_osr *temp_osr;
int (*reset)(struct device *dev); int (*reset)(struct device *dev);
int (*read_prom_word)(struct device *dev, int index, u16 *word); int (*read_prom_word)(struct device *dev, int index, u16 *word);
int (*read_adc_temp_and_pressure)(struct device *dev, int (*read_adc_temp_and_pressure)(struct device *dev,
s32 *temp, s32 *pressure); s32 *temp, s32 *pressure);
struct ms5611_chip_info *chip_info; struct ms5611_chip_info *chip_info;
struct regulator *vdd;
}; };
int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
......
...@@ -18,11 +18,44 @@ ...@@ -18,11 +18,44 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/iio/triggered_buffer.h> #include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h> #include <linux/iio/trigger_consumer.h>
#include "ms5611.h" #include "ms5611.h"
#define MS5611_INIT_OSR(_cmd, _conv_usec, _rate) \
{ .cmd = _cmd, .conv_usec = _conv_usec, .rate = _rate }
static const struct ms5611_osr ms5611_avail_pressure_osr[] = {
MS5611_INIT_OSR(0x40, 600, 256),
MS5611_INIT_OSR(0x42, 1170, 512),
MS5611_INIT_OSR(0x44, 2280, 1024),
MS5611_INIT_OSR(0x46, 4540, 2048),
MS5611_INIT_OSR(0x48, 9040, 4096)
};
static const struct ms5611_osr ms5611_avail_temp_osr[] = {
MS5611_INIT_OSR(0x50, 600, 256),
MS5611_INIT_OSR(0x52, 1170, 512),
MS5611_INIT_OSR(0x54, 2280, 1024),
MS5611_INIT_OSR(0x56, 4540, 2048),
MS5611_INIT_OSR(0x58, 9040, 4096)
};
static const char ms5611_show_osr[] = "256 512 1024 2048 4096";
static IIO_CONST_ATTR(oversampling_ratio_available, ms5611_show_osr);
static struct attribute *ms5611_attributes[] = {
&iio_const_attr_oversampling_ratio_available.dev_attr.attr,
NULL,
};
static const struct attribute_group ms5611_attribute_group = {
.attrs = ms5611_attributes,
};
static bool ms5611_prom_is_valid(u16 *prom, size_t len) static bool ms5611_prom_is_valid(u16 *prom, size_t len)
{ {
int i, j; int i, j;
...@@ -239,11 +272,70 @@ static int ms5611_read_raw(struct iio_dev *indio_dev, ...@@ -239,11 +272,70 @@ static int ms5611_read_raw(struct iio_dev *indio_dev,
default: default:
return -EINVAL; return -EINVAL;
} }
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
if (chan->type != IIO_TEMP && chan->type != IIO_PRESSURE)
break;
mutex_lock(&st->lock);
if (chan->type == IIO_TEMP)
*val = (int)st->temp_osr->rate;
else
*val = (int)st->pressure_osr->rate;
mutex_unlock(&st->lock);
return IIO_VAL_INT;
} }
return -EINVAL; return -EINVAL;
} }
static const struct ms5611_osr *ms5611_find_osr(int rate,
const struct ms5611_osr *osr,
size_t count)
{
unsigned int r;
for (r = 0; r < count; r++)
if ((unsigned short)rate == osr[r].rate)
break;
if (r >= count)
return NULL;
return &osr[r];
}
static int ms5611_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct ms5611_state *st = iio_priv(indio_dev);
const struct ms5611_osr *osr = NULL;
if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO)
return -EINVAL;
if (chan->type == IIO_TEMP)
osr = ms5611_find_osr(val, ms5611_avail_temp_osr,
ARRAY_SIZE(ms5611_avail_temp_osr));
else if (chan->type == IIO_PRESSURE)
osr = ms5611_find_osr(val, ms5611_avail_pressure_osr,
ARRAY_SIZE(ms5611_avail_pressure_osr));
if (!osr)
return -EINVAL;
mutex_lock(&st->lock);
if (iio_buffer_enabled(indio_dev)) {
mutex_unlock(&st->lock);
return -EBUSY;
}
if (chan->type == IIO_TEMP)
st->temp_osr = osr;
else
st->pressure_osr = osr;
mutex_unlock(&st->lock);
return 0;
}
static const unsigned long ms5611_scan_masks[] = {0x3, 0}; static const unsigned long ms5611_scan_masks[] = {0x3, 0};
static struct ms5611_chip_info chip_info_tbl[] = { static struct ms5611_chip_info chip_info_tbl[] = {
...@@ -259,7 +351,8 @@ static const struct iio_chan_spec ms5611_channels[] = { ...@@ -259,7 +351,8 @@ static const struct iio_chan_spec ms5611_channels[] = {
{ {
.type = IIO_PRESSURE, .type = IIO_PRESSURE,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_SCALE), BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
.scan_index = 0, .scan_index = 0,
.scan_type = { .scan_type = {
.sign = 's', .sign = 's',
...@@ -271,7 +364,8 @@ static const struct iio_chan_spec ms5611_channels[] = { ...@@ -271,7 +364,8 @@ static const struct iio_chan_spec ms5611_channels[] = {
{ {
.type = IIO_TEMP, .type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_SCALE), BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
.scan_index = 1, .scan_index = 1,
.scan_type = { .scan_type = {
.sign = 's', .sign = 's',
...@@ -285,30 +379,53 @@ static const struct iio_chan_spec ms5611_channels[] = { ...@@ -285,30 +379,53 @@ static const struct iio_chan_spec ms5611_channels[] = {
static const struct iio_info ms5611_info = { static const struct iio_info ms5611_info = {
.read_raw = &ms5611_read_raw, .read_raw = &ms5611_read_raw,
.write_raw = &ms5611_write_raw,
.attrs = &ms5611_attribute_group,
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
}; };
static int ms5611_init(struct iio_dev *indio_dev) static int ms5611_init(struct iio_dev *indio_dev)
{ {
int ret; int ret;
struct regulator *vdd = devm_regulator_get(indio_dev->dev.parent, struct ms5611_state *st = iio_priv(indio_dev);
"vdd");
/* Enable attached regulator if any. */ /* Enable attached regulator if any. */
if (!IS_ERR(vdd)) { st->vdd = devm_regulator_get(indio_dev->dev.parent, "vdd");
ret = regulator_enable(vdd); if (!IS_ERR(st->vdd)) {
ret = regulator_enable(st->vdd);
if (ret) { if (ret) {
dev_err(indio_dev->dev.parent, dev_err(indio_dev->dev.parent,
"failed to enable Vdd supply: %d\n", ret); "failed to enable Vdd supply: %d\n", ret);
return ret; return ret;
} }
} else {
ret = PTR_ERR(st->vdd);
if (ret != -ENODEV)
return ret;
} }
ret = ms5611_reset(indio_dev); ret = ms5611_reset(indio_dev);
if (ret < 0) if (ret < 0)
return ret; goto err_regulator_disable;
return ms5611_read_prom(indio_dev); ret = ms5611_read_prom(indio_dev);
if (ret < 0)
goto err_regulator_disable;
return 0;
err_regulator_disable:
if (!IS_ERR_OR_NULL(st->vdd))
regulator_disable(st->vdd);
return ret;
}
static void ms5611_fini(const struct iio_dev *indio_dev)
{
const struct ms5611_state *st = iio_priv(indio_dev);
if (!IS_ERR_OR_NULL(st->vdd))
regulator_disable(st->vdd);
} }
int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
...@@ -319,6 +436,11 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, ...@@ -319,6 +436,11 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
mutex_init(&st->lock); mutex_init(&st->lock);
st->chip_info = &chip_info_tbl[type]; st->chip_info = &chip_info_tbl[type];
st->temp_osr =
&ms5611_avail_temp_osr[ARRAY_SIZE(ms5611_avail_temp_osr) - 1];
st->pressure_osr =
&ms5611_avail_pressure_osr[ARRAY_SIZE(ms5611_avail_pressure_osr)
- 1];
indio_dev->dev.parent = dev; indio_dev->dev.parent = dev;
indio_dev->name = name; indio_dev->name = name;
indio_dev->info = &ms5611_info; indio_dev->info = &ms5611_info;
...@@ -335,7 +457,7 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, ...@@ -335,7 +457,7 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
ms5611_trigger_handler, NULL); ms5611_trigger_handler, NULL);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "iio triggered buffer setup failed\n"); dev_err(dev, "iio triggered buffer setup failed\n");
return ret; goto err_fini;
} }
ret = iio_device_register(indio_dev); ret = iio_device_register(indio_dev);
...@@ -348,7 +470,8 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, ...@@ -348,7 +470,8 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
err_buffer_cleanup: err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev); iio_triggered_buffer_cleanup(indio_dev);
err_fini:
ms5611_fini(indio_dev);
return ret; return ret;
} }
EXPORT_SYMBOL(ms5611_probe); EXPORT_SYMBOL(ms5611_probe);
...@@ -357,6 +480,7 @@ int ms5611_remove(struct iio_dev *indio_dev) ...@@ -357,6 +480,7 @@ int ms5611_remove(struct iio_dev *indio_dev)
{ {
iio_device_unregister(indio_dev); iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev); iio_triggered_buffer_cleanup(indio_dev);
ms5611_fini(indio_dev);
return 0; return 0;
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h>
#include "ms5611.h" #include "ms5611.h"
...@@ -62,23 +63,23 @@ static int ms5611_i2c_read_adc_temp_and_pressure(struct device *dev, ...@@ -62,23 +63,23 @@ static int ms5611_i2c_read_adc_temp_and_pressure(struct device *dev,
{ {
int ret; int ret;
struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev)); struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
const struct ms5611_osr *osr = st->temp_osr;
ret = i2c_smbus_write_byte(st->client, MS5611_START_TEMP_CONV); ret = i2c_smbus_write_byte(st->client, osr->cmd);
if (ret < 0) if (ret < 0)
return ret; return ret;
usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX); usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
ret = ms5611_i2c_read_adc(st, temp); ret = ms5611_i2c_read_adc(st, temp);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = i2c_smbus_write_byte(st->client, MS5611_START_PRESSURE_CONV); osr = st->pressure_osr;
ret = i2c_smbus_write_byte(st->client, osr->cmd);
if (ret < 0) if (ret < 0)
return ret; return ret;
usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX); usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
return ms5611_i2c_read_adc(st, pressure); return ms5611_i2c_read_adc(st, pressure);
} }
...@@ -113,6 +114,17 @@ static int ms5611_i2c_remove(struct i2c_client *client) ...@@ -113,6 +114,17 @@ static int ms5611_i2c_remove(struct i2c_client *client)
return ms5611_remove(i2c_get_clientdata(client)); return ms5611_remove(i2c_get_clientdata(client));
} }
#if defined(CONFIG_OF)
static const struct of_device_id ms5611_i2c_matches[] = {
{ .compatible = "meas,ms5611" },
{ .compatible = "ms5611" },
{ .compatible = "meas,ms5607" },
{ .compatible = "ms5607" },
{ }
};
MODULE_DEVICE_TABLE(of, ms5611_i2c_matches);
#endif
static const struct i2c_device_id ms5611_id[] = { static const struct i2c_device_id ms5611_id[] = {
{ "ms5611", MS5611 }, { "ms5611", MS5611 },
{ "ms5607", MS5607 }, { "ms5607", MS5607 },
...@@ -123,6 +135,7 @@ MODULE_DEVICE_TABLE(i2c, ms5611_id); ...@@ -123,6 +135,7 @@ MODULE_DEVICE_TABLE(i2c, ms5611_id);
static struct i2c_driver ms5611_driver = { static struct i2c_driver ms5611_driver = {
.driver = { .driver = {
.name = "ms5611", .name = "ms5611",
.of_match_table = of_match_ptr(ms5611_i2c_matches)
}, },
.id_table = ms5611_id, .id_table = ms5611_id,
.probe = ms5611_i2c_probe, .probe = ms5611_i2c_probe,
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/of_device.h>
#include "ms5611.h" #include "ms5611.h"
...@@ -55,28 +56,29 @@ static int ms5611_spi_read_adc(struct device *dev, s32 *val) ...@@ -55,28 +56,29 @@ static int ms5611_spi_read_adc(struct device *dev, s32 *val)
static int ms5611_spi_read_adc_temp_and_pressure(struct device *dev, static int ms5611_spi_read_adc_temp_and_pressure(struct device *dev,
s32 *temp, s32 *pressure) s32 *temp, s32 *pressure)
{ {
u8 cmd;
int ret; int ret;
struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev)); struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
const struct ms5611_osr *osr = st->temp_osr;
cmd = MS5611_START_TEMP_CONV; /*
ret = spi_write_then_read(st->client, &cmd, 1, NULL, 0); * Warning: &osr->cmd MUST be aligned on a word boundary since used as
* 2nd argument (void*) of spi_write_then_read.
*/
ret = spi_write_then_read(st->client, &osr->cmd, 1, NULL, 0);
if (ret < 0) if (ret < 0)
return ret; return ret;
usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX); usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
ret = ms5611_spi_read_adc(dev, temp); ret = ms5611_spi_read_adc(dev, temp);
if (ret < 0) if (ret < 0)
return ret; return ret;
cmd = MS5611_START_PRESSURE_CONV; osr = st->pressure_osr;
ret = spi_write_then_read(st->client, &cmd, 1, NULL, 0); ret = spi_write_then_read(st->client, &osr->cmd, 1, NULL, 0);
if (ret < 0) if (ret < 0)
return ret; return ret;
usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX); usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
return ms5611_spi_read_adc(dev, pressure); return ms5611_spi_read_adc(dev, pressure);
} }
...@@ -114,6 +116,17 @@ static int ms5611_spi_remove(struct spi_device *spi) ...@@ -114,6 +116,17 @@ static int ms5611_spi_remove(struct spi_device *spi)
return ms5611_remove(spi_get_drvdata(spi)); return ms5611_remove(spi_get_drvdata(spi));
} }
#if defined(CONFIG_OF)
static const struct of_device_id ms5611_spi_matches[] = {
{ .compatible = "meas,ms5611" },
{ .compatible = "ms5611" },
{ .compatible = "meas,ms5607" },
{ .compatible = "ms5607" },
{ }
};
MODULE_DEVICE_TABLE(of, ms5611_spi_matches);
#endif
static const struct spi_device_id ms5611_id[] = { static const struct spi_device_id ms5611_id[] = {
{ "ms5611", MS5611 }, { "ms5611", MS5611 },
{ "ms5607", MS5607 }, { "ms5607", MS5607 },
...@@ -124,6 +137,7 @@ MODULE_DEVICE_TABLE(spi, ms5611_id); ...@@ -124,6 +137,7 @@ MODULE_DEVICE_TABLE(spi, ms5611_id);
static struct spi_driver ms5611_driver = { static struct spi_driver ms5611_driver = {
.driver = { .driver = {
.name = "ms5611", .name = "ms5611",
.of_match_table = of_match_ptr(ms5611_spi_matches)
}, },
.id_table = ms5611_id, .id_table = ms5611_id,
.probe = ms5611_spi_probe, .probe = ms5611_spi_probe,
......
...@@ -27,18 +27,6 @@ config ADIS16203 ...@@ -27,18 +27,6 @@ config ADIS16203
To compile this driver as a module, say M here: the module will be To compile this driver as a module, say M here: the module will be
called adis16203. called adis16203.
config ADIS16204
tristate "Analog Devices ADIS16204 Programmable High-g Digital Impact Sensor and Recorder"
depends on SPI
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say Y here to build support for Analog Devices adis16204 Programmable
High-g Digital Impact Sensor and Recorder.
To compile this driver as a module, say M here: the module will be
called adis16204.
config ADIS16209 config ADIS16209
tristate "Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer" tristate "Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer"
depends on SPI depends on SPI
...@@ -51,17 +39,6 @@ config ADIS16209 ...@@ -51,17 +39,6 @@ config ADIS16209
To compile this driver as a module, say M here: the module will be To compile this driver as a module, say M here: the module will be
called adis16209. called adis16209.
config ADIS16220
tristate "Analog Devices ADIS16220 Programmable Digital Vibration Sensor"
depends on SPI
select IIO_ADIS_LIB
help
Say Y here to build support for Analog Devices adis16220 programmable
digital vibration sensor.
To compile this driver as a module, say M here: the module will be
called adis16220.
config ADIS16240 config ADIS16240
tristate "Analog Devices ADIS16240 Programmable Impact Sensor and Recorder" tristate "Analog Devices ADIS16240 Programmable Impact Sensor and Recorder"
depends on SPI depends on SPI
......
...@@ -8,15 +8,9 @@ obj-$(CONFIG_ADIS16201) += adis16201.o ...@@ -8,15 +8,9 @@ obj-$(CONFIG_ADIS16201) += adis16201.o
adis16203-y := adis16203_core.o adis16203-y := adis16203_core.o
obj-$(CONFIG_ADIS16203) += adis16203.o obj-$(CONFIG_ADIS16203) += adis16203.o
adis16204-y := adis16204_core.o
obj-$(CONFIG_ADIS16204) += adis16204.o
adis16209-y := adis16209_core.o adis16209-y := adis16209_core.o
obj-$(CONFIG_ADIS16209) += adis16209.o obj-$(CONFIG_ADIS16209) += adis16209.o
adis16220-y := adis16220_core.o
obj-$(CONFIG_ADIS16220) += adis16220.o
adis16240-y := adis16240_core.o adis16240-y := adis16240_core.o
obj-$(CONFIG_ADIS16240) += adis16240.o obj-$(CONFIG_ADIS16240) += adis16240.o
......
#ifndef SPI_ADIS16204_H_
#define SPI_ADIS16204_H_
#define ADIS16204_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16204_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16204_SUPPLY_OUT 0x02
/* Output, x-axis accelerometer */
#define ADIS16204_XACCL_OUT 0x04
/* Output, y-axis accelerometer */
#define ADIS16204_YACCL_OUT 0x06
/* Output, auxiliary ADC input */
#define ADIS16204_AUX_ADC 0x08
/* Output, temperature */
#define ADIS16204_TEMP_OUT 0x0A
/* Twos complement */
#define ADIS16204_X_PEAK_OUT 0x0C
#define ADIS16204_Y_PEAK_OUT 0x0E
/* Calibration, x-axis acceleration offset null */
#define ADIS16204_XACCL_NULL 0x10
/* Calibration, y-axis acceleration offset null */
#define ADIS16204_YACCL_NULL 0x12
/* X-axis scale factor calibration register */
#define ADIS16204_XACCL_SCALE 0x14
/* Y-axis scale factor calibration register */
#define ADIS16204_YACCL_SCALE 0x16
/* XY combined acceleration (RSS) */
#define ADIS16204_XY_RSS_OUT 0x18
/* Peak, XY combined output (RSS) */
#define ADIS16204_XY_PEAK_OUT 0x1A
/* Capture buffer output register 1 */
#define ADIS16204_CAP_BUF_1 0x1C
/* Capture buffer output register 2 */
#define ADIS16204_CAP_BUF_2 0x1E
/* Alarm 1 amplitude threshold */
#define ADIS16204_ALM_MAG1 0x20
/* Alarm 2 amplitude threshold */
#define ADIS16204_ALM_MAG2 0x22
/* Alarm control */
#define ADIS16204_ALM_CTRL 0x28
/* Capture register address pointer */
#define ADIS16204_CAPT_PNTR 0x2A
/* Auxiliary DAC data */
#define ADIS16204_AUX_DAC 0x30
/* General-purpose digital input/output control */
#define ADIS16204_GPIO_CTRL 0x32
/* Miscellaneous control */
#define ADIS16204_MSC_CTRL 0x34
/* Internal sample period (rate) control */
#define ADIS16204_SMPL_PRD 0x36
/* Operation, filter configuration */
#define ADIS16204_AVG_CNT 0x38
/* Operation, sleep mode control */
#define ADIS16204_SLP_CNT 0x3A
/* Diagnostics, system status register */
#define ADIS16204_DIAG_STAT 0x3C
/* Operation, system command register */
#define ADIS16204_GLOB_CMD 0x3E
/* MSC_CTRL */
/* Self-test at power-on: 1 = disabled, 0 = enabled */
#define ADIS16204_MSC_CTRL_PWRUP_SELF_TEST BIT(10)
/* Self-test enable */
#define ADIS16204_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16204_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16204_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO2, 0 = DIO1 */
#define ADIS16204_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16204_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16204_DIAG_STAT_ALARM1 BIT(8)
/* Self-test diagnostic error flag: 1 = error condition, 0 = normal operation */
#define ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT 5
/* SPI communications failure */
#define ADIS16204_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16204_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16204_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 2.975 V */
#define ADIS16204_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16204_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16204_GLOB_CMD_CLEAR_STAT BIT(4)
#define ADIS16204_GLOB_CMD_FACTORY_CAL BIT(1)
#define ADIS16204_ERROR_ACTIVE BIT(14)
enum adis16204_scan {
ADIS16204_SCAN_ACC_X,
ADIS16204_SCAN_ACC_Y,
ADIS16204_SCAN_ACC_XY,
ADIS16204_SCAN_SUPPLY,
ADIS16204_SCAN_AUX_ADC,
ADIS16204_SCAN_TEMP,
};
#endif /* SPI_ADIS16204_H_ */
/*
* ADIS16204 Programmable High-g Digital Impact Sensor and Recorder
*
* Copyright 2010 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
#include <linux/iio/imu/adis.h>
#include "adis16204.h"
/* Unique to this driver currently */
static const u8 adis16204_addresses[][2] = {
[ADIS16204_SCAN_ACC_X] = { ADIS16204_XACCL_NULL, ADIS16204_X_PEAK_OUT },
[ADIS16204_SCAN_ACC_Y] = { ADIS16204_YACCL_NULL, ADIS16204_Y_PEAK_OUT },
[ADIS16204_SCAN_ACC_XY] = { 0, ADIS16204_XY_PEAK_OUT },
};
static int adis16204_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2,
long mask)
{
struct adis *st = iio_priv(indio_dev);
int ret;
int bits;
u8 addr;
s16 val16;
int addrind;
switch (mask) {
case IIO_CHAN_INFO_RAW:
return adis_single_conversion(indio_dev, chan,
ADIS16204_ERROR_ACTIVE, val);
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
if (chan->channel == 0) {
*val = 1;
*val2 = 220000; /* 1.22 mV */
} else {
*val = 0;
*val2 = 610000; /* 0.61 mV */
}
return IIO_VAL_INT_PLUS_MICRO;
case IIO_TEMP:
*val = -470; /* 0.47 C */
*val2 = 0;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_ACCEL:
*val = 0;
switch (chan->channel2) {
case IIO_MOD_X:
case IIO_MOD_ROOT_SUM_SQUARED_X_Y:
*val2 = IIO_G_TO_M_S_2(17125); /* 17.125 mg */
break;
case IIO_MOD_Y:
case IIO_MOD_Z:
*val2 = IIO_G_TO_M_S_2(8407); /* 8.407 mg */
break;
}
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
break;
case IIO_CHAN_INFO_OFFSET:
*val = 25000 / -470 - 1278; /* 25 C = 1278 */
return IIO_VAL_INT;
case IIO_CHAN_INFO_CALIBBIAS:
case IIO_CHAN_INFO_PEAK:
if (mask == IIO_CHAN_INFO_CALIBBIAS) {
bits = 12;
addrind = 0;
} else { /* PEAK_SEPARATE */
bits = 14;
addrind = 1;
}
mutex_lock(&indio_dev->mlock);
addr = adis16204_addresses[chan->scan_index][addrind];
ret = adis_read_reg_16(st, addr, &val16);
if (ret) {
mutex_unlock(&indio_dev->mlock);
return ret;
}
val16 &= (1 << bits) - 1;
val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
*val = val16;
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
}
return -EINVAL;
}
static int adis16204_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val,
int val2,
long mask)
{
struct adis *st = iio_priv(indio_dev);
int bits;
s16 val16;
u8 addr;
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) {
case IIO_ACCEL:
bits = 12;
break;
default:
return -EINVAL;
}
val16 = val & ((1 << bits) - 1);
addr = adis16204_addresses[chan->scan_index][1];
return adis_write_reg_16(st, addr, val16);
}
return -EINVAL;
}
static const struct iio_chan_spec adis16204_channels[] = {
ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 0, 12),
ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 0, 12),
ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 0, 12),
ADIS_ACCEL_CHAN(X, ADIS16204_XACCL_OUT, ADIS16204_SCAN_ACC_X,
BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK),
0, 14),
ADIS_ACCEL_CHAN(Y, ADIS16204_YACCL_OUT, ADIS16204_SCAN_ACC_Y,
BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK),
0, 14),
ADIS_ACCEL_CHAN(ROOT_SUM_SQUARED_X_Y, ADIS16204_XY_RSS_OUT,
ADIS16204_SCAN_ACC_XY, BIT(IIO_CHAN_INFO_PEAK), 0, 14),
IIO_CHAN_SOFT_TIMESTAMP(5),
};
static const struct iio_info adis16204_info = {
.read_raw = &adis16204_read_raw,
.write_raw = &adis16204_write_raw,
.update_scan_mode = adis_update_scan_mode,
.driver_module = THIS_MODULE,
};
static const char * const adis16204_status_error_msgs[] = {
[ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT] = "Self test failure",
[ADIS16204_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
[ADIS16204_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
[ADIS16204_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
[ADIS16204_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.975V",
};
static const struct adis_data adis16204_data = {
.read_delay = 20,
.msc_ctrl_reg = ADIS16204_MSC_CTRL,
.glob_cmd_reg = ADIS16204_GLOB_CMD,
.diag_stat_reg = ADIS16204_DIAG_STAT,
.self_test_mask = ADIS16204_MSC_CTRL_SELF_TEST_EN,
.startup_delay = ADIS16204_STARTUP_DELAY,
.status_error_msgs = adis16204_status_error_msgs,
.status_error_mask = BIT(ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT) |
BIT(ADIS16204_DIAG_STAT_SPI_FAIL_BIT) |
BIT(ADIS16204_DIAG_STAT_FLASH_UPT_BIT) |
BIT(ADIS16204_DIAG_STAT_POWER_HIGH_BIT) |
BIT(ADIS16204_DIAG_STAT_POWER_LOW_BIT),
};
static int adis16204_probe(struct spi_device *spi)
{
int ret;
struct adis *st;
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
/* this is only used for removal purposes */
spi_set_drvdata(spi, indio_dev);
indio_dev->name = spi->dev.driver->name;
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &adis16204_info;
indio_dev->channels = adis16204_channels;
indio_dev->num_channels = ARRAY_SIZE(adis16204_channels);
indio_dev->modes = INDIO_DIRECT_MODE;
ret = adis_init(st, indio_dev, spi, &adis16204_data);
if (ret)
return ret;
ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
if (ret)
return ret;
/* Get the device into a sane initial state */
ret = adis_initial_startup(st);
if (ret)
goto error_cleanup_buffer_trigger;
ret = iio_device_register(indio_dev);
if (ret)
goto error_cleanup_buffer_trigger;
return 0;
error_cleanup_buffer_trigger:
adis_cleanup_buffer_and_trigger(st, indio_dev);
return ret;
}
static int adis16204_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct adis *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
adis_cleanup_buffer_and_trigger(st, indio_dev);
return 0;
}
static struct spi_driver adis16204_driver = {
.driver = {
.name = "adis16204",
},
.probe = adis16204_probe,
.remove = adis16204_remove,
};
module_spi_driver(adis16204_driver);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("ADIS16204 High-g Digital Impact Sensor and Recorder");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:adis16204");
#ifndef SPI_ADIS16220_H_
#define SPI_ADIS16220_H_
#include <linux/iio/imu/adis.h>
#define ADIS16220_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16220_FLASH_CNT 0x00
/* Control, acceleration offset adjustment control */
#define ADIS16220_ACCL_NULL 0x02
/* Control, AIN1 offset adjustment control */
#define ADIS16220_AIN1_NULL 0x04
/* Control, AIN2 offset adjustment control */
#define ADIS16220_AIN2_NULL 0x06
/* Output, power supply during capture */
#define ADIS16220_CAPT_SUPPLY 0x0A
/* Output, temperature during capture */
#define ADIS16220_CAPT_TEMP 0x0C
/* Output, peak acceleration during capture */
#define ADIS16220_CAPT_PEAKA 0x0E
/* Output, peak AIN1 level during capture */
#define ADIS16220_CAPT_PEAK1 0x10
/* Output, peak AIN2 level during capture */
#define ADIS16220_CAPT_PEAK2 0x12
/* Output, capture buffer for acceleration */
#define ADIS16220_CAPT_BUFA 0x14
/* Output, capture buffer for AIN1 */
#define ADIS16220_CAPT_BUF1 0x16
/* Output, capture buffer for AIN2 */
#define ADIS16220_CAPT_BUF2 0x18
/* Control, capture buffer address pointer */
#define ADIS16220_CAPT_PNTR 0x1A
/* Control, capture control register */
#define ADIS16220_CAPT_CTRL 0x1C
/* Control, capture period (automatic mode) */
#define ADIS16220_CAPT_PRD 0x1E
/* Control, Alarm A, acceleration peak threshold */
#define ADIS16220_ALM_MAGA 0x20
/* Control, Alarm 1, AIN1 peak threshold */
#define ADIS16220_ALM_MAG1 0x22
/* Control, Alarm 2, AIN2 peak threshold */
#define ADIS16220_ALM_MAG2 0x24
/* Control, Alarm S, peak threshold */
#define ADIS16220_ALM_MAGS 0x26
/* Control, alarm configuration register */
#define ADIS16220_ALM_CTRL 0x28
/* Control, general I/O configuration */
#define ADIS16220_GPIO_CTRL 0x32
/* Control, self-test control, AIN configuration */
#define ADIS16220_MSC_CTRL 0x34
/* Control, digital I/O configuration */
#define ADIS16220_DIO_CTRL 0x36
/* Control, filter configuration */
#define ADIS16220_AVG_CNT 0x38
/* Status, system status */
#define ADIS16220_DIAG_STAT 0x3C
/* Control, system commands */
#define ADIS16220_GLOB_CMD 0x3E
/* Status, self-test response */
#define ADIS16220_ST_DELTA 0x40
/* Lot Identification Code 1 */
#define ADIS16220_LOT_ID1 0x52
/* Lot Identification Code 2 */
#define ADIS16220_LOT_ID2 0x54
/* Product identifier; convert to decimal = 16220 */
#define ADIS16220_PROD_ID 0x56
/* Serial number */
#define ADIS16220_SERIAL_NUM 0x58
#define ADIS16220_CAPTURE_SIZE 2048
/* MSC_CTRL */
#define ADIS16220_MSC_CTRL_SELF_TEST_EN BIT(8)
#define ADIS16220_MSC_CTRL_POWER_SUP_COM_AIN1 BIT(1)
#define ADIS16220_MSC_CTRL_POWER_SUP_COM_AIN2 BIT(0)
/* DIO_CTRL */
#define ADIS16220_MSC_CTRL_DIO2_BUSY_IND (BIT(5) | BIT(4))
#define ADIS16220_MSC_CTRL_DIO1_BUSY_IND (BIT(3) | BIT(2))
#define ADIS16220_MSC_CTRL_DIO2_ACT_HIGH BIT(1)
#define ADIS16220_MSC_CTRL_DIO1_ACT_HIGH BIT(0)
/* DIAG_STAT */
/* AIN2 sample > ALM_MAG2 */
#define ADIS16220_DIAG_STAT_ALM_MAG2 BIT(14)
/* AIN1 sample > ALM_MAG1 */
#define ADIS16220_DIAG_STAT_ALM_MAG1 BIT(13)
/* Acceleration sample > ALM_MAGA */
#define ADIS16220_DIAG_STAT_ALM_MAGA BIT(12)
/* Error condition programmed into ALM_MAGS[11:0] and ALM_CTRL[5:4] is true */
#define ADIS16220_DIAG_STAT_ALM_MAGS BIT(11)
/* |Peak value in AIN2 data capture| > ALM_MAG2 */
#define ADIS16220_DIAG_STAT_PEAK_AIN2 BIT(10)
/* |Peak value in AIN1 data capture| > ALM_MAG1 */
#define ADIS16220_DIAG_STAT_PEAK_AIN1 BIT(9)
/* |Peak value in acceleration data capture| > ALM_MAGA */
#define ADIS16220_DIAG_STAT_PEAK_ACCEL BIT(8)
/* Data ready, capture complete */
#define ADIS16220_DIAG_STAT_DATA_RDY BIT(7)
#define ADIS16220_DIAG_STAT_FLASH_CHK BIT(6)
#define ADIS16220_DIAG_STAT_SELF_TEST BIT(5)
/* Capture period violation/interruption */
#define ADIS16220_DIAG_STAT_VIOLATION_BIT 4
/* SPI communications failure */
#define ADIS16220_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16220_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16220_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16220_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16220_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16220_GLOB_CMD_SELF_TEST BIT(2)
#define ADIS16220_GLOB_CMD_PWR_DOWN BIT(1)
#define ADIS16220_MAX_TX 2048
#define ADIS16220_MAX_RX 2048
#define ADIS16220_SPI_BURST (u32)(1000 * 1000)
#define ADIS16220_SPI_FAST (u32)(2000 * 1000)
/**
* struct adis16220_state - device instance specific data
* @adis: adis device
* @tx: transmit buffer
* @rx: receive buffer
* @buf_lock: mutex to protect tx and rx
**/
struct adis16220_state {
struct adis adis;
struct mutex buf_lock;
u8 tx[ADIS16220_MAX_TX] ____cacheline_aligned;
u8 rx[ADIS16220_MAX_RX];
};
#endif /* SPI_ADIS16220_H_ */
This diff is collapsed.
...@@ -349,11 +349,9 @@ static ssize_t ad7192_write_frequency(struct device *dev, ...@@ -349,11 +349,9 @@ static ssize_t ad7192_write_frequency(struct device *dev,
if (lval == 0) if (lval == 0)
return -EINVAL; return -EINVAL;
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (iio_buffer_enabled(indio_dev)) { if (ret)
mutex_unlock(&indio_dev->mlock); return ret;
return -EBUSY;
}
div = st->mclk / (lval * st->f_order * 1024); div = st->mclk / (lval * st->f_order * 1024);
if (div < 1 || div > 1023) { if (div < 1 || div > 1023) {
...@@ -366,7 +364,7 @@ static ssize_t ad7192_write_frequency(struct device *dev, ...@@ -366,7 +364,7 @@ static ssize_t ad7192_write_frequency(struct device *dev,
ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
out: out:
mutex_unlock(&indio_dev->mlock); iio_device_release_direct_mode(indio_dev);
return ret ? ret : len; return ret ? ret : len;
} }
...@@ -434,11 +432,9 @@ static ssize_t ad7192_set(struct device *dev, ...@@ -434,11 +432,9 @@ static ssize_t ad7192_set(struct device *dev,
if (ret < 0) if (ret < 0)
return ret; return ret;
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (iio_buffer_enabled(indio_dev)) { if (ret)
mutex_unlock(&indio_dev->mlock); return ret;
return -EBUSY;
}
switch ((u32)this_attr->address) { switch ((u32)this_attr->address) {
case AD7192_REG_GPOCON: case AD7192_REG_GPOCON:
...@@ -461,7 +457,7 @@ static ssize_t ad7192_set(struct device *dev, ...@@ -461,7 +457,7 @@ static ssize_t ad7192_set(struct device *dev,
ret = -EINVAL; ret = -EINVAL;
} }
mutex_unlock(&indio_dev->mlock); iio_device_release_direct_mode(indio_dev);
return ret ? ret : len; return ret ? ret : len;
} }
...@@ -555,11 +551,9 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, ...@@ -555,11 +551,9 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
int ret, i; int ret, i;
unsigned int tmp; unsigned int tmp;
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (iio_buffer_enabled(indio_dev)) { if (ret)
mutex_unlock(&indio_dev->mlock); return ret;
return -EBUSY;
}
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
...@@ -582,7 +576,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, ...@@ -582,7 +576,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
ret = -EINVAL; ret = -EINVAL;
} }
mutex_unlock(&indio_dev->mlock); iio_device_release_direct_mode(indio_dev);
return ret; return ret;
} }
......
...@@ -155,7 +155,7 @@ static void ad7280_crc8_build_table(unsigned char *crc_tab) ...@@ -155,7 +155,7 @@ static void ad7280_crc8_build_table(unsigned char *crc_tab)
} }
} }
static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned val) static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned int val)
{ {
unsigned char crc; unsigned char crc;
...@@ -165,7 +165,7 @@ static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned val) ...@@ -165,7 +165,7 @@ static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned val)
return crc ^ (val & 0xFF); return crc ^ (val & 0xFF);
} }
static int ad7280_check_crc(struct ad7280_state *st, unsigned val) static int ad7280_check_crc(struct ad7280_state *st, unsigned int val)
{ {
unsigned char crc = ad7280_calc_crc8(st->crc_tab, val >> 10); unsigned char crc = ad7280_calc_crc8(st->crc_tab, val >> 10);
...@@ -191,7 +191,7 @@ static void ad7280_delay(struct ad7280_state *st) ...@@ -191,7 +191,7 @@ static void ad7280_delay(struct ad7280_state *st)
usleep_range(250, 500); usleep_range(250, 500);
} }
static int __ad7280_read32(struct ad7280_state *st, unsigned *val) static int __ad7280_read32(struct ad7280_state *st, unsigned int *val)
{ {
int ret; int ret;
struct spi_transfer t = { struct spi_transfer t = {
...@@ -211,10 +211,10 @@ static int __ad7280_read32(struct ad7280_state *st, unsigned *val) ...@@ -211,10 +211,10 @@ static int __ad7280_read32(struct ad7280_state *st, unsigned *val)
return 0; return 0;
} }
static int ad7280_write(struct ad7280_state *st, unsigned devaddr, static int ad7280_write(struct ad7280_state *st, unsigned int devaddr,
unsigned addr, bool all, unsigned val) unsigned int addr, bool all, unsigned int val)
{ {
unsigned reg = devaddr << 27 | addr << 21 | unsigned int reg = devaddr << 27 | addr << 21 |
(val & 0xFF) << 13 | all << 12; (val & 0xFF) << 13 | all << 12;
reg |= ad7280_calc_crc8(st->crc_tab, reg >> 11) << 3 | 0x2; reg |= ad7280_calc_crc8(st->crc_tab, reg >> 11) << 3 | 0x2;
...@@ -223,11 +223,11 @@ static int ad7280_write(struct ad7280_state *st, unsigned devaddr, ...@@ -223,11 +223,11 @@ static int ad7280_write(struct ad7280_state *st, unsigned devaddr,
return spi_write(st->spi, &st->buf[0], 4); return spi_write(st->spi, &st->buf[0], 4);
} }
static int ad7280_read(struct ad7280_state *st, unsigned devaddr, static int ad7280_read(struct ad7280_state *st, unsigned int devaddr,
unsigned addr) unsigned int addr)
{ {
int ret; int ret;
unsigned tmp; unsigned int tmp;
/* turns off the read operation on all parts */ /* turns off the read operation on all parts */
ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1, ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1,
...@@ -261,11 +261,11 @@ static int ad7280_read(struct ad7280_state *st, unsigned devaddr, ...@@ -261,11 +261,11 @@ static int ad7280_read(struct ad7280_state *st, unsigned devaddr,
return (tmp >> 13) & 0xFF; return (tmp >> 13) & 0xFF;
} }
static int ad7280_read_channel(struct ad7280_state *st, unsigned devaddr, static int ad7280_read_channel(struct ad7280_state *st, unsigned int devaddr,
unsigned addr) unsigned int addr)
{ {
int ret; int ret;
unsigned tmp; unsigned int tmp;
ret = ad7280_write(st, devaddr, AD7280A_READ, 0, addr << 2); ret = ad7280_write(st, devaddr, AD7280A_READ, 0, addr << 2);
if (ret) if (ret)
...@@ -299,11 +299,11 @@ static int ad7280_read_channel(struct ad7280_state *st, unsigned devaddr, ...@@ -299,11 +299,11 @@ static int ad7280_read_channel(struct ad7280_state *st, unsigned devaddr,
return (tmp >> 11) & 0xFFF; return (tmp >> 11) & 0xFFF;
} }
static int ad7280_read_all_channels(struct ad7280_state *st, unsigned cnt, static int ad7280_read_all_channels(struct ad7280_state *st, unsigned int cnt,
unsigned *array) unsigned int *array)
{ {
int i, ret; int i, ret;
unsigned tmp, sum = 0; unsigned int tmp, sum = 0;
ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ, 1, ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ, 1,
AD7280A_CELL_VOLTAGE_1 << 2); AD7280A_CELL_VOLTAGE_1 << 2);
...@@ -338,7 +338,7 @@ static int ad7280_read_all_channels(struct ad7280_state *st, unsigned cnt, ...@@ -338,7 +338,7 @@ static int ad7280_read_all_channels(struct ad7280_state *st, unsigned cnt,
static int ad7280_chain_setup(struct ad7280_state *st) static int ad7280_chain_setup(struct ad7280_state *st)
{ {
unsigned val, n; unsigned int val, n;
int ret; int ret;
ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_LB, 1, ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_LB, 1,
...@@ -401,7 +401,7 @@ static ssize_t ad7280_store_balance_sw(struct device *dev, ...@@ -401,7 +401,7 @@ static ssize_t ad7280_store_balance_sw(struct device *dev,
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
bool readin; bool readin;
int ret; int ret;
unsigned devaddr, ch; unsigned int devaddr, ch;
ret = strtobool(buf, &readin); ret = strtobool(buf, &readin);
if (ret) if (ret)
...@@ -431,7 +431,7 @@ static ssize_t ad7280_show_balance_timer(struct device *dev, ...@@ -431,7 +431,7 @@ static ssize_t ad7280_show_balance_timer(struct device *dev,
struct ad7280_state *st = iio_priv(indio_dev); struct ad7280_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret; int ret;
unsigned msecs; unsigned int msecs;
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
ret = ad7280_read(st, this_attr->address >> 8, ret = ad7280_read(st, this_attr->address >> 8,
...@@ -602,7 +602,7 @@ static ssize_t ad7280_read_channel_config(struct device *dev, ...@@ -602,7 +602,7 @@ static ssize_t ad7280_read_channel_config(struct device *dev,
struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7280_state *st = iio_priv(indio_dev); struct ad7280_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
unsigned val; unsigned int val;
switch ((u32)this_attr->address) { switch ((u32)this_attr->address) {
case AD7280A_CELL_OVERVOLTAGE: case AD7280A_CELL_OVERVOLTAGE:
...@@ -683,7 +683,7 @@ static irqreturn_t ad7280_event_handler(int irq, void *private) ...@@ -683,7 +683,7 @@ static irqreturn_t ad7280_event_handler(int irq, void *private)
{ {
struct iio_dev *indio_dev = private; struct iio_dev *indio_dev = private;
struct ad7280_state *st = iio_priv(indio_dev); struct ad7280_state *st = iio_priv(indio_dev);
unsigned *channels; unsigned int *channels;
int i, ret; int i, ret;
channels = kcalloc(st->scan_cnt, sizeof(*channels), GFP_KERNEL); channels = kcalloc(st->scan_cnt, sizeof(*channels), GFP_KERNEL);
......
...@@ -29,10 +29,10 @@ ...@@ -29,10 +29,10 @@
#define AD7280A_ALERT_REMOVE_AUX4_AUX5 BIT(1) #define AD7280A_ALERT_REMOVE_AUX4_AUX5 BIT(1)
struct ad7280_platform_data { struct ad7280_platform_data {
unsigned acquisition_time; unsigned int acquisition_time;
unsigned conversion_averaging; unsigned int conversion_averaging;
unsigned chain_last_alert_ignore; unsigned int chain_last_alert_ignore;
bool thermistor_term_en; bool thermistor_term_en;
}; };
#endif /* IIO_ADC_AD7280_H_ */ #endif /* IIO_ADC_AD7280_H_ */
This diff is collapsed.
...@@ -36,7 +36,7 @@ int ad7606_reset(struct ad7606_state *st) ...@@ -36,7 +36,7 @@ int ad7606_reset(struct ad7606_state *st)
return -ENODEV; return -ENODEV;
} }
static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned ch) static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch)
{ {
struct ad7606_state *st = iio_priv(indio_dev); struct ad7606_state *st = iio_priv(indio_dev);
int ret; int ret;
...@@ -155,7 +155,7 @@ static ssize_t ad7606_show_oversampling_ratio(struct device *dev, ...@@ -155,7 +155,7 @@ static ssize_t ad7606_show_oversampling_ratio(struct device *dev,
return sprintf(buf, "%u\n", st->oversampling); return sprintf(buf, "%u\n", st->oversampling);
} }
static int ad7606_oversampling_get_index(unsigned val) static int ad7606_oversampling_get_index(unsigned int val)
{ {
unsigned char supported[] = {0, 2, 4, 8, 16, 32, 64}; unsigned char supported[] = {0, 2, 4, 8, 16, 32, 64};
int i; int i;
...@@ -446,7 +446,7 @@ static const struct iio_info ad7606_info_range = { ...@@ -446,7 +446,7 @@ static const struct iio_info ad7606_info_range = {
struct iio_dev *ad7606_probe(struct device *dev, int irq, struct iio_dev *ad7606_probe(struct device *dev, int irq,
void __iomem *base_address, void __iomem *base_address,
unsigned id, unsigned int id,
const struct ad7606_bus_ops *bops) const struct ad7606_bus_ops *bops)
{ {
struct ad7606_platform_data *pdata = dev->platform_data; struct ad7606_platform_data *pdata = dev->platform_data;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment