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
Contact: linux-iio@vger.kernel.org
Description:
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.
Often these sensors are unit less and as such conversion
to SI units is not possible. Higher proximity measurements
......@@ -1255,12 +1255,23 @@ Description:
What: /sys/.../iio:deviceX/in_intensityY_raw
What: /sys/.../iio:deviceX/in_intensityY_ir_raw
What: /sys/.../iio:deviceX/in_intensityY_both_raw
What: /sys/.../iio:deviceX/in_intensityY_uv_raw
KernelVersion: 3.4
Contact: linux-iio@vger.kernel.org
Description:
Unit-less light intensity. Modifiers both and ir indicate
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_green_integration_time
......
Freescale MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC or MMA8653FC
Freescale MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC or FXLS8471Q
triaxial accelerometer
Required properties:
......@@ -9,6 +9,7 @@ Required properties:
* "fsl,mma8453"
* "fsl,mma8652"
* "fsl,mma8653"
* "fsl,fxls8471"
- 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
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
region.
- 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:
Optional properties:
- 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:
......@@ -15,4 +16,5 @@ ak8975@0c {
compatible = "asahi-kasei,ak8975";
reg = <0x0c>;
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:
- st,lsm330-accel
- st,lsm303agr-accel
- st,lis2dh12-accel
- st,h3lis331dl-accel
Gyroscopes:
- st,l3g4200d-gyro
......
......@@ -141,6 +141,7 @@ lsi LSI Corp. (LSI Logic)
lltc Linear Technology Corporation
marvell Marvell Technology Group Ltd.
maxim Maxim Integrated Products
meas Measurement Specialties
mediatek MediaTek Inc.
melexis Melexis N.V.
merrii Merrii Technology Co., Ltd.
......
......@@ -5538,7 +5538,7 @@ IIO SUBSYSTEM AND DRIVERS
M: Jonathan Cameron <jic23@kernel.org>
R: Hartmut Knaack <knaack.h@gmx.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
S: Maintained
F: drivers/iio/
......
......@@ -64,7 +64,7 @@ config IIO_ST_ACCEL_3AXIS
help
Say yes here to build support for STMicroelectronics accelerometers:
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
will be created:
......@@ -143,7 +143,8 @@ config MMA8452
select IIO_TRIGGERED_BUFFER
help
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
will be called mma8452.
......
......@@ -25,7 +25,6 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
......@@ -138,6 +137,7 @@ enum bmc150_accel_axis {
AXIS_X,
AXIS_Y,
AXIS_Z,
AXIS_MAX,
};
enum bmc150_power_modes {
......@@ -246,11 +246,12 @@ static const struct {
{500000, BMC150_ACCEL_SLEEP_500_MS},
{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,
.val_bits = 8,
.max_register = 0x3f,
};
EXPORT_SYMBOL_GPL(bmc150_regmap_conf);
static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
enum bmc150_power_modes mode,
......@@ -988,6 +989,7 @@ static const struct iio_event_spec bmc150_accel_event = {
.realbits = (bits), \
.storagebits = 16, \
.shift = 16 - (bits), \
.endianness = IIO_LE, \
}, \
.event_spec = &bmc150_accel_event, \
.num_event_specs = 1 \
......@@ -1104,27 +1106,23 @@ static const struct iio_info bmc150_accel_info_fifo = {
.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)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmc150_accel_data *data = iio_priv(indio_dev);
int bit, ret, i = 0;
unsigned int raw_val;
int ret;
mutex_lock(&data->mutex);
for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->masklength) {
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;
}
ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_REG_XOUT_L,
data->buffer, AXIS_MAX * 2);
mutex_unlock(&data->mutex);
if (ret < 0)
goto err_read;
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
pf->timestamp);
......@@ -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->num_channels = data->chip_info->num_channels;
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->info = &bmc150_accel_info;
......
......@@ -28,11 +28,6 @@
#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,
const struct i2c_device_id *id)
{
......@@ -43,7 +38,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
i2c_check_functionality(client->adapter,
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)) {
dev_err(&client->dev, "Failed to initialize i2c regmap\n");
return PTR_ERR(regmap);
......
......@@ -25,18 +25,12 @@
#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)
{
struct regmap *regmap;
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)) {
dev_err(&spi->dev, "Failed to initialize spi regmap\n");
return PTR_ERR(regmap);
......
......@@ -16,5 +16,6 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
const char *name, bool block_supported);
int bmc150_accel_core_remove(struct device *dev);
extern const struct dev_pm_ops bmc150_accel_pm_ops;
extern const struct regmap_config bmc150_regmap_conf;
#endif /* _BMC150_ACCEL_H_ */
......@@ -20,7 +20,6 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
......@@ -115,6 +114,7 @@ enum kxcjk1013_axis {
AXIS_X,
AXIS_Y,
AXIS_Z,
AXIS_MAX,
};
enum kxcjk1013_mode {
......@@ -922,7 +922,7 @@ static const struct iio_event_spec kxcjk1013_event = {
.realbits = 12, \
.storagebits = 16, \
.shift = 4, \
.endianness = IIO_CPU, \
.endianness = IIO_LE, \
}, \
.event_spec = &kxcjk1013_event, \
.num_event_specs = 1 \
......@@ -953,25 +953,23 @@ static const struct iio_info kxcjk1013_info = {
.driver_module = THIS_MODULE,
};
static const unsigned long kxcjk1013_scan_masks[] = {0x7, 0};
static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct kxcjk1013_data *data = iio_priv(indio_dev);
int bit, ret, i = 0;
int ret;
mutex_lock(&data->mutex);
for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->masklength) {
ret = kxcjk1013_get_acc_reg(data, bit);
if (ret < 0) {
mutex_unlock(&data->mutex);
goto err;
}
data->buffer[i++] = ret;
}
ret = i2c_smbus_read_i2c_block_data_or_emulated(data->client,
KXCJK1013_REG_XOUT_L,
AXIS_MAX * 2,
(u8 *)data->buffer);
mutex_unlock(&data->mutex);
if (ret < 0)
goto err;
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
data->timestamp);
......@@ -1204,6 +1202,7 @@ static int kxcjk1013_probe(struct i2c_client *client,
indio_dev->dev.parent = &client->dev;
indio_dev->channels = kxcjk1013_channels;
indio_dev->num_channels = ARRAY_SIZE(kxcjk1013_channels);
indio_dev->available_scan_masks = kxcjk1013_scan_masks;
indio_dev->name = name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &kxcjk1013_info;
......
......@@ -6,6 +6,7 @@
* MMA8453Q (10 bit)
* MMA8652FC (12 bit)
* MMA8653FC (10 bit)
* FXLS8471Q (14 bit)
*
* Copyright 2015 Martin Kepplinger <martin.kepplinger@theobroma-systems.com>
* Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net>
......@@ -16,7 +17,7 @@
*
* 7-bit I2C slave address 0x1c/0x1d (pin selectable)
*
* TODO: orientation events, autosleep
* TODO: orientation events
*/
#include <linux/module.h>
......@@ -31,6 +32,7 @@
#include <linux/delay.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/pm_runtime.h>
#define MMA8452_STATUS 0x00
#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
......@@ -91,6 +93,9 @@
#define MMA8453_DEVICE_ID 0x3a
#define MMA8652_DEVICE_ID 0x4a
#define MMA8653_DEVICE_ID 0x5a
#define FXLS8471_DEVICE_ID 0x6a
#define MMA8452_AUTO_SUSPEND_DELAY_MS 2000
struct mma8452_data {
struct i2c_client *client;
......@@ -172,6 +177,31 @@ static int mma8452_drdy(struct mma8452_data *data)
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])
{
int ret = mma8452_drdy(data);
......@@ -179,8 +209,16 @@ static int mma8452_read(struct mma8452_data *data, __be16 buf[3])
if (ret < 0)
return ret;
return i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X,
3 * sizeof(__be16), (u8 *)buf);
ret = mma8452_set_runtime_pm_state(data->client, true);
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],
......@@ -357,7 +395,8 @@ static int mma8452_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_CALIBBIAS:
ret = i2c_smbus_read_byte_data(data->client,
MMA8452_OFF_X + chan->scan_index);
MMA8452_OFF_X +
chan->scan_index);
if (ret < 0)
return ret;
......@@ -392,24 +431,47 @@ static int mma8452_active(struct mma8452_data *data)
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)
{
int ret;
int is_active;
mutex_lock(&data->lock);
/* config can only be changed when in standby */
ret = mma8452_standby(data);
if (ret < 0)
is_active = mma8452_is_active(data);
if (is_active < 0) {
ret = is_active;
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);
if (ret < 0)
goto fail;
ret = mma8452_active(data);
if (ret < 0)
goto fail;
if (is_active > 0) {
ret = mma8452_active(data);
if (ret < 0)
goto fail;
}
ret = 0;
fail:
......@@ -418,7 +480,7 @@ static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val)
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)
{
int val;
......@@ -668,7 +730,8 @@ static int mma8452_read_event_config(struct iio_dev *indio_dev,
if (ret < 0)
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:
return -EINVAL;
}
......@@ -682,7 +745,11 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev,
{
struct mma8452_data *data = iio_priv(indio_dev);
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) {
case IIO_EV_DIR_FALLING:
......@@ -990,6 +1057,7 @@ enum {
mma8453,
mma8652,
mma8653,
fxls8471,
};
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.
* The userspace interface uses m/s^2 and we declare micro units
* 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} },
.ev_cfg = MMA8452_TRANSIENT_CFG,
......@@ -1081,6 +1149,22 @@ static const struct mma_chip_info mma_chip_info_table[] = {
.ev_ths_mask = MMA8452_FF_MT_THS_MASK,
.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[] = {
......@@ -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 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);
if (reg < 0)
......@@ -1206,6 +1294,7 @@ static const struct of_device_id mma8452_dt_ids[] = {
{ .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] },
{ .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] },
{ .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);
......@@ -1243,6 +1332,7 @@ static int mma8452_probe(struct i2c_client *client,
case MMA8453_DEVICE_ID:
case MMA8652_DEVICE_ID:
case MMA8653_DEVICE_ID:
case FXLS8471_DEVICE_ID:
if (ret == data->chip_info->chip_id)
break;
default:
......@@ -1340,6 +1430,15 @@ static int mma8452_probe(struct i2c_client *client,
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);
if (ret < 0)
goto buffer_cleanup;
......@@ -1364,6 +1463,11 @@ static int mma8452_remove(struct i2c_client *client)
struct iio_dev *indio_dev = i2c_get_clientdata(client);
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);
mma8452_trigger_cleanup(indio_dev);
mma8452_standby(iio_priv(indio_dev));
......@@ -1371,6 +1475,45 @@ static int mma8452_remove(struct i2c_client *client)
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
static int mma8452_suspend(struct device *dev)
{
......@@ -1383,18 +1526,21 @@ static int mma8452_resume(struct device *dev)
return mma8452_active(iio_priv(i2c_get_clientdata(
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
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[] = {
{ "mma8451", mma8451 },
{ "mma8452", mma8452 },
{ "mma8453", mma8453 },
{ "mma8652", mma8652 },
{ "mma8653", mma8653 },
{ "fxls8471", fxls8471 },
{ }
};
MODULE_DEVICE_TABLE(i2c, mma8452_id);
......@@ -1403,7 +1549,7 @@ static struct i2c_driver mma8452_driver = {
.driver = {
.name = "mma8452",
.of_match_table = of_match_ptr(mma8452_dt_ids),
.pm = MMA8452_PM_OPS,
.pm = &mma8452_pm_ops,
},
.probe = mma8452_probe,
.remove = mma8452_remove,
......
......@@ -17,7 +17,6 @@
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
......
......@@ -17,7 +17,6 @@
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/regmap.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
......@@ -380,31 +379,6 @@ static const struct iio_trigger_ops mxc4005_trigger_ops = {
.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)
{
int ret;
......@@ -470,9 +444,6 @@ static int mxc4005_probe(struct i2c_client *client,
return ret;
}
if (client->irq < 0)
client->irq = mxc4005_gpio_probe(client, data);
if (client->irq > 0) {
data->dready_trig = devm_iio_trigger_alloc(&client->dev,
"%s-dev%d",
......
......@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/iio/common/st_sensors.h>
#define H3LIS331DL_DRIVER_NAME "h3lis331dl_accel"
#define LIS3LV02DL_ACCEL_DEV_NAME "lis3lv02dl_accel"
#define LSM303DLHC_ACCEL_DEV_NAME "lsm303dlhc_accel"
#define LIS3DH_ACCEL_DEV_NAME "lis3dh"
......
......@@ -39,6 +39,9 @@
#define ST_ACCEL_FS_AVL_6G 6
#define ST_ACCEL_FS_AVL_8G 8
#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 */
#define ST_ACCEL_1_WAI_EXP 0x33
......@@ -181,6 +184,33 @@
#define ST_ACCEL_5_IG1_EN_MASK 0x08
#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[] = {
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
......@@ -557,6 +587,68 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT,
.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,
......
......@@ -76,6 +76,10 @@ static const struct of_device_id st_accel_of_match[] = {
.compatible = "st,lis2dh12-accel",
.data = LIS2DH12_ACCEL_DEV_NAME,
},
{
.compatible = "st,h3lis331dl-accel",
.data = H3LIS331DL_DRIVER_NAME,
},
{},
};
MODULE_DEVICE_TABLE(of, st_accel_of_match);
......
......@@ -11,7 +11,6 @@
*/
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
......
......@@ -11,7 +11,6 @@
*/
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
......
......@@ -134,6 +134,7 @@ config AT91_ADC
config AT91_SAMA5D2_ADC
tristate "Atmel AT91 SAMA5D2 ADC"
depends on ARCH_AT91 || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to build support for Atmel SAMA5D2 ADC which is
available on SAMA5D2 SoC family.
......@@ -241,6 +242,16 @@ config LP8788_ADC
To compile this driver as a module, choose M here: the module will be
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
tristate "Maxim max1027 ADC driver"
depends on SPI
......
......@@ -25,6 +25,7 @@ obj-$(CONFIG_HI8435) += hi8435.o
obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_MAX1027) += max1027.o
obj-$(CONFIG_MAX1363) += max1363.o
obj-$(CONFIG_MCP320X) += mcp320x.o
......
......@@ -66,8 +66,10 @@
#define AT91_SAMA5D2_MR_PRESCAL(v) ((v) << AT91_SAMA5D2_MR_PRESCAL_OFFSET)
#define AT91_SAMA5D2_MR_PRESCAL_OFFSET 8
#define AT91_SAMA5D2_MR_PRESCAL_MAX 0xff
#define AT91_SAMA5D2_MR_PRESCAL_MASK GENMASK(15, 8)
/* Startup Time */
#define AT91_SAMA5D2_MR_STARTUP(v) ((v) << 16)
#define AT91_SAMA5D2_MR_STARTUP_MASK GENMASK(19, 16)
/* Analog Change */
#define AT91_SAMA5D2_MR_ANACH BIT(23)
/* Tracking Time */
......@@ -92,13 +94,13 @@
/* Last Converted Data Register */
#define AT91_SAMA5D2_LCDR 0x20
/* Interrupt Enable Register */
#define AT91_SAMA5D2_IER 0x24
#define AT91_SAMA5D2_IER 0x24
/* Interrupt Disable Register */
#define AT91_SAMA5D2_IDR 0x28
#define AT91_SAMA5D2_IDR 0x28
/* Interrupt Mask Register */
#define AT91_SAMA5D2_IMR 0x2c
#define AT91_SAMA5D2_IMR 0x2c
/* Interrupt Status Register */
#define AT91_SAMA5D2_ISR 0x30
#define AT91_SAMA5D2_ISR 0x30
/* Last Channel Trigger Mode Register */
#define AT91_SAMA5D2_LCTMR 0x34
/* Last Channel Compare Window Register */
......@@ -106,17 +108,20 @@
/* Overrun Status Register */
#define AT91_SAMA5D2_OVER 0x3c
/* Extended Mode Register */
#define AT91_SAMA5D2_EMR 0x40
#define AT91_SAMA5D2_EMR 0x40
/* Compare Window Register */
#define AT91_SAMA5D2_CWR 0x44
#define AT91_SAMA5D2_CWR 0x44
/* Channel Gain Register */
#define AT91_SAMA5D2_CGR 0x48
#define AT91_SAMA5D2_CGR 0x48
/* Channel Offset Register */
#define AT91_SAMA5D2_COR 0x4c
#define AT91_SAMA5D2_COR 0x4c
#define AT91_SAMA5D2_COR_DIFF_OFFSET 16
/* Channel Data Register 0 */
#define AT91_SAMA5D2_CDR0 0x50
/* Analog Control Register */
#define AT91_SAMA5D2_ACR 0x94
#define AT91_SAMA5D2_ACR 0x94
/* Touchscreen Mode Register */
#define AT91_SAMA5D2_TSMR 0xb0
/* Touchscreen X Position Register */
......@@ -130,7 +135,7 @@
/* Correction Select Register */
#define AT91_SAMA5D2_COSR 0xd0
/* Correction Value Register */
#define AT91_SAMA5D2_CVR 0xd4
#define AT91_SAMA5D2_CVR 0xd4
/* Channel Error Correction Register */
#define AT91_SAMA5D2_CECR 0xd8
/* Write Protection Mode Register */
......@@ -140,7 +145,7 @@
/* Version Register */
#define AT91_SAMA5D2_VERSION 0xfc
#define AT91_AT91_SAMA5D2_CHAN(num, addr) \
#define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \
{ \
.type = IIO_VOLTAGE, \
.channel = num, \
......@@ -156,6 +161,24 @@
.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_writel(st, reg, val) writel_relaxed(val, st->base + reg)
......@@ -185,18 +208,24 @@ struct at91_adc_state {
};
static const struct iio_chan_spec at91_adc_channels[] = {
AT91_AT91_SAMA5D2_CHAN(0, 0x50),
AT91_AT91_SAMA5D2_CHAN(1, 0x54),
AT91_AT91_SAMA5D2_CHAN(2, 0x58),
AT91_AT91_SAMA5D2_CHAN(3, 0x5c),
AT91_AT91_SAMA5D2_CHAN(4, 0x60),
AT91_AT91_SAMA5D2_CHAN(5, 0x64),
AT91_AT91_SAMA5D2_CHAN(6, 0x68),
AT91_AT91_SAMA5D2_CHAN(7, 0x6c),
AT91_AT91_SAMA5D2_CHAN(8, 0x70),
AT91_AT91_SAMA5D2_CHAN(9, 0x74),
AT91_AT91_SAMA5D2_CHAN(10, 0x78),
AT91_AT91_SAMA5D2_CHAN(11, 0x7c),
AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
AT91_SAMA5D2_CHAN_SINGLE(2, 0x58),
AT91_SAMA5D2_CHAN_SINGLE(3, 0x5c),
AT91_SAMA5D2_CHAN_SINGLE(4, 0x60),
AT91_SAMA5D2_CHAN_SINGLE(5, 0x64),
AT91_SAMA5D2_CHAN_SINGLE(6, 0x68),
AT91_SAMA5D2_CHAN_SINGLE(7, 0x6c),
AT91_SAMA5D2_CHAN_SINGLE(8, 0x70),
AT91_SAMA5D2_CHAN_SINGLE(9, 0x74),
AT91_SAMA5D2_CHAN_SINGLE(10, 0x78),
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,
......@@ -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)
{
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);
prescal = (f_per / (2 * freq)) - 1;
......@@ -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,
freq / 1000);
at91_adc_writel(st, AT91_SAMA5D2_MR,
AT91_SAMA5D2_MR_TRANSFER(2)
| AT91_SAMA5D2_MR_STARTUP(startup)
| AT91_SAMA5D2_MR_PRESCAL(prescal));
mr = at91_adc_readl(st, AT91_SAMA5D2_MR);
mr &= ~(AT91_SAMA5D2_MR_STARTUP_MASK | AT91_SAMA5D2_MR_PRESCAL_MASK);
mr |= AT91_SAMA5D2_MR_STARTUP(startup);
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",
freq, startup, prescal);
......@@ -278,6 +308,7 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct at91_adc_state *st = iio_priv(indio_dev);
u32 cor = 0;
int ret;
switch (mask) {
......@@ -286,6 +317,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
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_IER, BIT(chan->channel));
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,
if (ret > 0) {
*val = st->conversion_value;
if (chan->scan_type.sign == 's')
*val = sign_extend32(*val, 11);
ret = IIO_VAL_INT;
st->conversion_done = false;
}
......@@ -310,6 +348,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
*val = st->vref_uv / 1000;
if (chan->differential)
*val *= 2;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
......@@ -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_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);
......
......@@ -185,9 +185,9 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
switch (chan->address) {
case INA2XX_SHUNT_VOLTAGE:
/* processed (mV) = raw*1000/shunt_div */
/* processed (mV) = raw/shunt_div */
*val2 = chip->config->shunt_div;
*val = 1000;
*val = 1;
return IIO_VAL_FRACTIONAL;
case INA2XX_BUS_VOLTAGE:
......@@ -350,6 +350,23 @@ static ssize_t ina2xx_allow_async_readout_store(struct device *dev,
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)
{
if (val <= 0 || val > chip->config->calibration_factor)
......@@ -385,6 +402,11 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
if (ret)
return ret;
/* Update the Calibration register */
ret = ina2xx_set_calibration(chip);
if (ret)
return ret;
return len;
}
......@@ -602,24 +624,11 @@ static const struct iio_info ina2xx_info = {
/* Initialize the configuration and calibration registers. */
static int ina2xx_init(struct ina2xx_chip_info *chip, unsigned int config)
{
u16 regval;
int ret;
ret = regmap_write(chip->regmap, INA2XX_CONFIG, config);
int ret = regmap_write(chip->regmap, INA2XX_CONFIG, config);
if (ret)
return ret;
/*
* 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);
return ina2xx_set_calibration(chip);
}
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 = {
.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[] = {
{
.compatible = "rockchip,saradc",
......@@ -166,6 +182,9 @@ static const struct of_device_id rockchip_saradc_match[] = {
}, {
.compatible = "rockchip,rk3066-tsadc",
.data = &rk3066_tsadc_data,
}, {
.compatible = "rockchip,rk3399-saradc",
.data = &rk3399_saradc_data,
},
{},
};
......
......@@ -24,19 +24,13 @@
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;
struct st_sensor_data *sdata = iio_priv(indio_dev);
unsigned int num_data_channels = sdata->num_data_channels;
unsigned int byte_for_channel =
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++) {
if (test_bit(i, indio_dev->active_scan_mask)) {
addr[n] = indio_dev->channels[i].address;
......@@ -57,10 +51,8 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
u8 *rx_array;
rx_array = kmalloc(byte_for_channel * num_data_channels,
GFP_KERNEL);
if (!rx_array) {
len = -ENOMEM;
goto st_sensors_free_memory;
}
if (!rx_array)
return -ENOMEM;
len = sdata->tf->read_multiple_byte(&sdata->tb,
sdata->dev, addr[0],
......@@ -68,7 +60,7 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
rx_array, sdata->multiread_bit);
if (len < 0) {
kfree(rx_array);
goto st_sensors_free_memory;
return len;
}
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)
buf, sdata->multiread_bit);
break;
default:
len = -EINVAL;
goto st_sensors_free_memory;
}
if (len != byte_for_channel * n) {
len = -EIO;
goto st_sensors_free_memory;
return -EINVAL;
}
if (len != byte_for_channel * n)
return -EIO;
st_sensors_free_memory:
kfree(addr);
st_sensors_get_buffer_element_error:
return len;
}
EXPORT_SYMBOL(st_sensors_get_buffer_element);
......
......@@ -154,6 +154,16 @@ config AD7303
To compile this driver as module choose M here: the module will be called
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
tristate "Mitsubishi M62332 DAC driver"
depends on I2C
......
......@@ -17,6 +17,7 @@ obj-$(CONFIG_AD5764) += ad5764.o
obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_AD7303) += ad7303.o
obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o
obj-$(CONFIG_M62332) += m62332.o
obj-$(CONFIG_MAX517) += max517.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 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
......@@ -31,7 +30,6 @@
#include "bmg160.h"
#define BMG160_IRQ_NAME "bmg160_event"
#define BMG160_GPIO_NAME "gpio_int"
#define BMG160_REG_CHIP_ID 0x00
#define BMG160_CHIP_ID_VAL 0x0F
......@@ -116,6 +114,7 @@ enum bmg160_axis {
AXIS_X,
AXIS_Y,
AXIS_Z,
AXIS_MAX,
};
static const struct {
......@@ -733,6 +732,7 @@ static const struct iio_event_spec bmg160_event = {
.sign = 's', \
.realbits = 16, \
.storagebits = 16, \
.endianness = IIO_LE, \
}, \
.event_spec = &bmg160_event, \
.num_event_specs = 1 \
......@@ -763,26 +763,23 @@ static const struct iio_info bmg160_info = {
.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)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmg160_data *data = iio_priv(indio_dev);
int bit, ret, i = 0;
unsigned int val;
int ret;
mutex_lock(&data->mutex);
for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->masklength) {
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;
}
ret = regmap_bulk_read(data->regmap, BMG160_REG_XOUT_L,
data->buffer, AXIS_MAX * 2);
mutex_unlock(&data->mutex);
if (ret < 0)
goto err;
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
pf->timestamp);
......@@ -955,29 +952,6 @@ static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = {
.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)
{
const struct acpi_device_id *id;
......@@ -1019,12 +993,10 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
indio_dev->channels = bmg160_channels;
indio_dev->num_channels = ARRAY_SIZE(bmg160_channels);
indio_dev->name = name;
indio_dev->available_scan_masks = bmg160_accel_scan_masks;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &bmg160_info;
if (data->irq <= 0)
bmg160_gpio_probe(data);
if (data->irq > 0) {
ret = devm_request_threaded_irq(dev,
data->irq,
......
......@@ -104,6 +104,19 @@ static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
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.
* @client: i2c client.
......@@ -115,14 +128,25 @@ static int inv_mpu_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct inv_mpu6050_state *st;
int result;
const char *name = id ? id->name : NULL;
int result, chip_type;
struct regmap *regmap;
const char *name;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_I2C_BLOCK))
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);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "Failed to register i2c regmap %d\n",
......@@ -131,7 +155,7 @@ static int inv_mpu_probe(struct i2c_client *client,
}
result = inv_mpu_core_probe(regmap, client->irq, name,
NULL, id->driver_data);
NULL, chip_type);
if (result < 0)
return result;
......
......@@ -46,6 +46,7 @@ static int inv_mpu_probe(struct spi_device *spi)
struct regmap *regmap;
const struct spi_device_id *id = spi_get_device_id(spi);
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);
if (IS_ERR(regmap)) {
......@@ -55,7 +56,7 @@ static int inv_mpu_probe(struct spi_device *spi)
}
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)
......
......@@ -14,7 +14,6 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
......
......@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/anon_inodes.h>
#include <linux/debugfs.h>
#include <linux/mutex.h>
#include <linux/iio/iio.h>
#include "iio_core.h"
#include "iio_core_trigger.h"
......@@ -78,6 +79,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_CONCENTRATION] = "concentration",
[IIO_RESISTANCE] = "resistance",
[IIO_PH] = "ph",
[IIO_UVINDEX] = "uvindex",
};
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_GREEN] = "green",
[IIO_MOD_LIGHT_BLUE] = "blue",
[IIO_MOD_LIGHT_UV] = "uv",
[IIO_MOD_QUATERNION] = "quaternion",
[IIO_MOD_TEMP_AMBIENT] = "ambient",
[IIO_MOD_TEMP_OBJECT] = "object",
......@@ -1375,6 +1378,44 @@ void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev)
}
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);
module_exit(iio_exit);
......
......@@ -16,7 +16,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/gpio/consumer.h>
#include <linux/iio/events.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
......
......@@ -806,8 +806,7 @@ static int tsl2563_probe(struct i2c_client *client,
return 0;
fail:
cancel_delayed_work(&chip->poweroff_work);
flush_scheduled_work();
cancel_delayed_work_sync(&chip->poweroff_work);
return err;
}
......
......@@ -32,6 +32,7 @@
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/acpi.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
......@@ -361,7 +362,6 @@ static const struct ak_def ak_def_array[AK_MAX_TYPE] = {
struct ak8975_data {
struct i2c_client *client;
const struct ak_def *def;
struct attribute_group attrs;
struct mutex lock;
u8 asa[3];
long raw_to_gauss[3];
......@@ -370,8 +370,40 @@ struct ak8975_data {
wait_queue_head_t data_ready_queue;
unsigned long flags;
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 a negative error number otherwise
......@@ -774,8 +806,11 @@ static int ak8975_probe(struct i2c_client *client,
if (id) {
chipset = (enum asahi_compass_chipset)(id->driver_data);
name = id->name;
} else if (ACPI_HANDLE(&client->dev))
} else if (ACPI_HANDLE(&client->dev)) {
name = ak8975_match_acpi_device(&client->dev, &chipset);
if (!name)
return -ENODEV;
}
else
return -ENOSYS;
......@@ -786,10 +821,15 @@ static int ak8975_probe(struct i2c_client *client,
}
data->def = &ak_def_array[chipset];
err = ak8975_power_on(client);
if (err)
return err;
err = ak8975_who_i_am(client, data->def->type);
if (err < 0) {
dev_err(&client->dev, "Unexpected device\n");
return err;
goto power_off;
}
dev_dbg(&client->dev, "Asahi compass chip %s\n", name);
......@@ -797,7 +837,7 @@ static int ak8975_probe(struct i2c_client *client,
err = ak8975_setup(client);
if (err < 0) {
dev_err(&client->dev, "%s initialization fails\n", name);
return err;
goto power_off;
}
mutex_init(&data->lock);
......@@ -807,7 +847,26 @@ static int ak8975_probe(struct i2c_client *client,
indio_dev->info = &ak8975_info;
indio_dev->modes = INDIO_DIRECT_MODE;
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[] = {
......@@ -841,6 +900,7 @@ static struct i2c_driver ak8975_driver = {
.acpi_match_table = ACPI_PTR(ak_acpi_match),
},
.probe = ak8975_probe,
.remove = ak8975_remove,
.id_table = ak8975_id,
};
module_i2c_driver(ak8975_driver);
......
......@@ -23,7 +23,6 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
......
......@@ -5,6 +5,24 @@
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
tristate "Microchip MCP45xx/MCP46xx Digital Potentiometer driver"
depends on I2C
......
......@@ -3,5 +3,6 @@
#
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_MCP4131) += mcp4131.o
obj-$(CONFIG_MCP4531) += mcp4531.o
obj-$(CONFIG_TPL0102) += tpl0102.o
/*
* Industrial I/O driver for Microchip digital potentiometers
*
* Copyright (c) 2016 Slawomir Stepien
* Based on: Peter Rosin's code from mcp4531.c
*
* Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf
*
* DEVID #Wipers #Positions Resistor Opts (kOhm)
* mcp4131 1 129 5, 10, 50, 100
* mcp4132 1 129 5, 10, 50, 100
* mcp4141 1 129 5, 10, 50, 100
* mcp4142 1 129 5, 10, 50, 100
* mcp4151 1 257 5, 10, 50, 100
* mcp4152 1 257 5, 10, 50, 100
* mcp4161 1 257 5, 10, 50, 100
* mcp4162 1 257 5, 10, 50, 100
* mcp4231 2 129 5, 10, 50, 100
* mcp4232 2 129 5, 10, 50, 100
* mcp4241 2 129 5, 10, 50, 100
* mcp4242 2 129 5, 10, 50, 100
* mcp4251 2 257 5, 10, 50, 100
* mcp4252 2 257 5, 10, 50, 100
* mcp4261 2 257 5, 10, 50, 100
* mcp4262 2 257 5, 10, 50, 100
*
* 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.
*/
/*
* TODO:
* 1. Write wiper setting to EEPROM for EEPROM capable models.
*/
#include <linux/cache.h>
#include <linux/err.h>
#include <linux/export.h>
#include <linux/iio/iio.h>
#include <linux/iio/types.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/spi/spi.h>
#define MCP4131_WRITE (0x00 << 2)
#define MCP4131_READ (0x03 << 2)
#define MCP4131_WIPER_SHIFT 4
#define MCP4131_CMDERR(r) ((r[0]) & 0x02)
#define MCP4131_RAW(r) ((r[0]) == 0xff ? 0x100 : (r[1]))
struct mcp4131_cfg {
int wipers;
int max_pos;
int kohms;
};
enum mcp4131_type {
MCP413x_502 = 0,
MCP413x_103,
MCP413x_503,
MCP413x_104,
MCP414x_502,
MCP414x_103,
MCP414x_503,
MCP414x_104,
MCP415x_502,
MCP415x_103,
MCP415x_503,
MCP415x_104,
MCP416x_502,
MCP416x_103,
MCP416x_503,
MCP416x_104,
MCP423x_502,
MCP423x_103,
MCP423x_503,
MCP423x_104,
MCP424x_502,
MCP424x_103,
MCP424x_503,
MCP424x_104,
MCP425x_502,
MCP425x_103,
MCP425x_503,
MCP425x_104,
MCP426x_502,
MCP426x_103,
MCP426x_503,
MCP426x_104,
};
static const struct mcp4131_cfg mcp4131_cfg[] = {
[MCP413x_502] = { .wipers = 1, .max_pos = 128, .kohms = 5, },
[MCP413x_103] = { .wipers = 1, .max_pos = 128, .kohms = 10, },
[MCP413x_503] = { .wipers = 1, .max_pos = 128, .kohms = 50, },
[MCP413x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, },
[MCP414x_502] = { .wipers = 1, .max_pos = 128, .kohms = 5, },
[MCP414x_103] = { .wipers = 1, .max_pos = 128, .kohms = 10, },
[MCP414x_503] = { .wipers = 1, .max_pos = 128, .kohms = 50, },
[MCP414x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, },
[MCP415x_502] = { .wipers = 1, .max_pos = 256, .kohms = 5, },
[MCP415x_103] = { .wipers = 1, .max_pos = 256, .kohms = 10, },
[MCP415x_503] = { .wipers = 1, .max_pos = 256, .kohms = 50, },
[MCP415x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, },
[MCP416x_502] = { .wipers = 1, .max_pos = 256, .kohms = 5, },
[MCP416x_103] = { .wipers = 1, .max_pos = 256, .kohms = 10, },
[MCP416x_503] = { .wipers = 1, .max_pos = 256, .kohms = 50, },
[MCP416x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, },
[MCP423x_502] = { .wipers = 2, .max_pos = 128, .kohms = 5, },
[MCP423x_103] = { .wipers = 2, .max_pos = 128, .kohms = 10, },
[MCP423x_503] = { .wipers = 2, .max_pos = 128, .kohms = 50, },
[MCP423x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, },
[MCP424x_502] = { .wipers = 2, .max_pos = 128, .kohms = 5, },
[MCP424x_103] = { .wipers = 2, .max_pos = 128, .kohms = 10, },
[MCP424x_503] = { .wipers = 2, .max_pos = 128, .kohms = 50, },
[MCP424x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, },
[MCP425x_502] = { .wipers = 2, .max_pos = 256, .kohms = 5, },
[MCP425x_103] = { .wipers = 2, .max_pos = 256, .kohms = 10, },
[MCP425x_503] = { .wipers = 2, .max_pos = 256, .kohms = 50, },
[MCP425x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, },
[MCP426x_502] = { .wipers = 2, .max_pos = 256, .kohms = 5, },
[MCP426x_103] = { .wipers = 2, .max_pos = 256, .kohms = 10, },
[MCP426x_503] = { .wipers = 2, .max_pos = 256, .kohms = 50, },
[MCP426x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, },
};
struct mcp4131_data {
struct spi_device *spi;
const struct mcp4131_cfg *cfg;
struct mutex lock;
u8 buf[2] ____cacheline_aligned;
};
#define MCP4131_CHANNEL(ch) { \
.type = IIO_RESISTANCE, \
.indexed = 1, \
.output = 1, \
.channel = (ch), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
static const struct iio_chan_spec mcp4131_channels[] = {
MCP4131_CHANNEL(0),
MCP4131_CHANNEL(1),
};
static int mcp4131_read(struct spi_device *spi, void *buf, size_t len)
{
struct spi_transfer t = {
.tx_buf = buf, /* We need to send addr, cmd and 12 bits */
.rx_buf = buf,
.len = len,
};
struct spi_message m;
spi_message_init(&m);
spi_message_add_tail(&t, &m);
return spi_sync(spi, &m);
}
static int mcp4131_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
int err;
struct mcp4131_data *data = iio_priv(indio_dev);
int address = chan->channel;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&data->lock);
data->buf[0] = (address << MCP4131_WIPER_SHIFT) | MCP4131_READ;
data->buf[1] = 0;
err = mcp4131_read(data->spi, data->buf, 2);
if (err) {
mutex_unlock(&data->lock);
return err;
}
/* Error, bad address/command combination */
if (!MCP4131_CMDERR(data->buf)) {
mutex_unlock(&data->lock);
return -EIO;
}
*val = MCP4131_RAW(data->buf);
mutex_unlock(&data->lock);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 1000 * data->cfg->kohms;
*val2 = data->cfg->max_pos;
return IIO_VAL_FRACTIONAL;
}
return -EINVAL;
}
static int mcp4131_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
int err;
struct mcp4131_data *data = iio_priv(indio_dev);
int address = chan->channel << MCP4131_WIPER_SHIFT;
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (val > data->cfg->max_pos || val < 0)
return -EINVAL;
break;
default:
return -EINVAL;
}
mutex_lock(&data->lock);
data->buf[0] = address << MCP4131_WIPER_SHIFT;
data->buf[0] |= MCP4131_WRITE | (val >> 8);
data->buf[1] = val & 0xFF; /* 8 bits here */
err = spi_write(data->spi, data->buf, 2);
mutex_unlock(&data->lock);
return err;
}
static const struct iio_info mcp4131_info = {
.read_raw = mcp4131_read_raw,
.write_raw = mcp4131_write_raw,
.driver_module = THIS_MODULE,
};
static int mcp4131_probe(struct spi_device *spi)
{
int err;
struct device *dev = &spi->dev;
unsigned long devid = spi_get_device_id(spi)->driver_data;
struct mcp4131_data *data;
struct iio_dev *indio_dev;
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
spi_set_drvdata(spi, indio_dev);
data->spi = spi;
data->cfg = &mcp4131_cfg[devid];
mutex_init(&data->lock);
indio_dev->dev.parent = dev;
indio_dev->info = &mcp4131_info;
indio_dev->channels = mcp4131_channels;
indio_dev->num_channels = data->cfg->wipers;
indio_dev->name = spi_get_device_id(spi)->name;
err = devm_iio_device_register(dev, indio_dev);
if (err) {
dev_info(&spi->dev, "Unable to register %s\n", indio_dev->name);
return err;
}
return 0;
}
#if defined(CONFIG_OF)
static const struct of_device_id mcp4131_dt_ids[] = {
{ .compatible = "microchip,mcp4131-502",
.data = &mcp4131_cfg[MCP413x_502] },
{ .compatible = "microchip,mcp4131-103",
.data = &mcp4131_cfg[MCP413x_103] },
{ .compatible = "microchip,mcp4131-503",
.data = &mcp4131_cfg[MCP413x_503] },
{ .compatible = "microchip,mcp4131-104",
.data = &mcp4131_cfg[MCP413x_104] },
{ .compatible = "microchip,mcp4132-502",
.data = &mcp4131_cfg[MCP413x_502] },
{ .compatible = "microchip,mcp4132-103",
.data = &mcp4131_cfg[MCP413x_103] },
{ .compatible = "microchip,mcp4132-503",
.data = &mcp4131_cfg[MCP413x_503] },
{ .compatible = "microchip,mcp4132-104",
.data = &mcp4131_cfg[MCP413x_104] },
{ .compatible = "microchip,mcp4141-502",
.data = &mcp4131_cfg[MCP414x_502] },
{ .compatible = "microchip,mcp4141-103",
.data = &mcp4131_cfg[MCP414x_103] },
{ .compatible = "microchip,mcp4141-503",
.data = &mcp4131_cfg[MCP414x_503] },
{ .compatible = "microchip,mcp4141-104",
.data = &mcp4131_cfg[MCP414x_104] },
{ .compatible = "microchip,mcp4142-502",
.data = &mcp4131_cfg[MCP414x_502] },
{ .compatible = "microchip,mcp4142-103",
.data = &mcp4131_cfg[MCP414x_103] },
{ .compatible = "microchip,mcp4142-503",
.data = &mcp4131_cfg[MCP414x_503] },
{ .compatible = "microchip,mcp4142-104",
.data = &mcp4131_cfg[MCP414x_104] },
{ .compatible = "microchip,mcp4151-502",
.data = &mcp4131_cfg[MCP415x_502] },
{ .compatible = "microchip,mcp4151-103",
.data = &mcp4131_cfg[MCP415x_103] },
{ .compatible = "microchip,mcp4151-503",
.data = &mcp4131_cfg[MCP415x_503] },
{ .compatible = "microchip,mcp4151-104",
.data = &mcp4131_cfg[MCP415x_104] },
{ .compatible = "microchip,mcp4152-502",
.data = &mcp4131_cfg[MCP415x_502] },
{ .compatible = "microchip,mcp4152-103",
.data = &mcp4131_cfg[MCP415x_103] },
{ .compatible = "microchip,mcp4152-503",
.data = &mcp4131_cfg[MCP415x_503] },
{ .compatible = "microchip,mcp4152-104",
.data = &mcp4131_cfg[MCP415x_104] },
{ .compatible = "microchip,mcp4161-502",
.data = &mcp4131_cfg[MCP416x_502] },
{ .compatible = "microchip,mcp4161-103",
.data = &mcp4131_cfg[MCP416x_103] },
{ .compatible = "microchip,mcp4161-503",
.data = &mcp4131_cfg[MCP416x_503] },
{ .compatible = "microchip,mcp4161-104",
.data = &mcp4131_cfg[MCP416x_104] },
{ .compatible = "microchip,mcp4162-502",
.data = &mcp4131_cfg[MCP416x_502] },
{ .compatible = "microchip,mcp4162-103",
.data = &mcp4131_cfg[MCP416x_103] },
{ .compatible = "microchip,mcp4162-503",
.data = &mcp4131_cfg[MCP416x_503] },
{ .compatible = "microchip,mcp4162-104",
.data = &mcp4131_cfg[MCP416x_104] },
{ .compatible = "microchip,mcp4231-502",
.data = &mcp4131_cfg[MCP423x_502] },
{ .compatible = "microchip,mcp4231-103",
.data = &mcp4131_cfg[MCP423x_103] },
{ .compatible = "microchip,mcp4231-503",
.data = &mcp4131_cfg[MCP423x_503] },
{ .compatible = "microchip,mcp4231-104",
.data = &mcp4131_cfg[MCP423x_104] },
{ .compatible = "microchip,mcp4232-502",
.data = &mcp4131_cfg[MCP423x_502] },
{ .compatible = "microchip,mcp4232-103",
.data = &mcp4131_cfg[MCP423x_103] },
{ .compatible = "microchip,mcp4232-503",
.data = &mcp4131_cfg[MCP423x_503] },
{ .compatible = "microchip,mcp4232-104",
.data = &mcp4131_cfg[MCP423x_104] },
{ .compatible = "microchip,mcp4241-502",
.data = &mcp4131_cfg[MCP424x_502] },
{ .compatible = "microchip,mcp4241-103",
.data = &mcp4131_cfg[MCP424x_103] },
{ .compatible = "microchip,mcp4241-503",
.data = &mcp4131_cfg[MCP424x_503] },
{ .compatible = "microchip,mcp4241-104",
.data = &mcp4131_cfg[MCP424x_104] },
{ .compatible = "microchip,mcp4242-502",
.data = &mcp4131_cfg[MCP424x_502] },
{ .compatible = "microchip,mcp4242-103",
.data = &mcp4131_cfg[MCP424x_103] },
{ .compatible = "microchip,mcp4242-503",
.data = &mcp4131_cfg[MCP424x_503] },
{ .compatible = "microchip,mcp4242-104",
.data = &mcp4131_cfg[MCP424x_104] },
{ .compatible = "microchip,mcp4251-502",
.data = &mcp4131_cfg[MCP425x_502] },
{ .compatible = "microchip,mcp4251-103",
.data = &mcp4131_cfg[MCP425x_103] },
{ .compatible = "microchip,mcp4251-503",
.data = &mcp4131_cfg[MCP425x_503] },
{ .compatible = "microchip,mcp4251-104",
.data = &mcp4131_cfg[MCP425x_104] },
{ .compatible = "microchip,mcp4252-502",
.data = &mcp4131_cfg[MCP425x_502] },
{ .compatible = "microchip,mcp4252-103",
.data = &mcp4131_cfg[MCP425x_103] },
{ .compatible = "microchip,mcp4252-503",
.data = &mcp4131_cfg[MCP425x_503] },
{ .compatible = "microchip,mcp4252-104",
.data = &mcp4131_cfg[MCP425x_104] },
{ .compatible = "microchip,mcp4261-502",
.data = &mcp4131_cfg[MCP426x_502] },
{ .compatible = "microchip,mcp4261-103",
.data = &mcp4131_cfg[MCP426x_103] },
{ .compatible = "microchip,mcp4261-503",
.data = &mcp4131_cfg[MCP426x_503] },
{ .compatible = "microchip,mcp4261-104",
.data = &mcp4131_cfg[MCP426x_104] },
{ .compatible = "microchip,mcp4262-502",
.data = &mcp4131_cfg[MCP426x_502] },
{ .compatible = "microchip,mcp4262-103",
.data = &mcp4131_cfg[MCP426x_103] },
{ .compatible = "microchip,mcp4262-503",
.data = &mcp4131_cfg[MCP426x_503] },
{ .compatible = "microchip,mcp4262-104",
.data = &mcp4131_cfg[MCP426x_104] },
{}
};
MODULE_DEVICE_TABLE(of, mcp4131_dt_ids);
#endif /* CONFIG_OF */
static const struct spi_device_id mcp4131_id[] = {
{ "mcp4131-502", MCP413x_502 },
{ "mcp4131-103", MCP413x_103 },
{ "mcp4131-503", MCP413x_503 },
{ "mcp4131-104", MCP413x_104 },
{ "mcp4132-502", MCP413x_502 },
{ "mcp4132-103", MCP413x_103 },
{ "mcp4132-503", MCP413x_503 },
{ "mcp4132-104", MCP413x_104 },
{ "mcp4141-502", MCP414x_502 },
{ "mcp4141-103", MCP414x_103 },
{ "mcp4141-503", MCP414x_503 },
{ "mcp4141-104", MCP414x_104 },
{ "mcp4142-502", MCP414x_502 },
{ "mcp4142-103", MCP414x_103 },
{ "mcp4142-503", MCP414x_503 },
{ "mcp4142-104", MCP414x_104 },
{ "mcp4151-502", MCP415x_502 },
{ "mcp4151-103", MCP415x_103 },
{ "mcp4151-503", MCP415x_503 },
{ "mcp4151-104", MCP415x_104 },
{ "mcp4152-502", MCP415x_502 },
{ "mcp4152-103", MCP415x_103 },
{ "mcp4152-503", MCP415x_503 },
{ "mcp4152-104", MCP415x_104 },
{ "mcp4161-502", MCP416x_502 },
{ "mcp4161-103", MCP416x_103 },
{ "mcp4161-503", MCP416x_503 },
{ "mcp4161-104", MCP416x_104 },
{ "mcp4162-502", MCP416x_502 },
{ "mcp4162-103", MCP416x_103 },
{ "mcp4162-503", MCP416x_503 },
{ "mcp4162-104", MCP416x_104 },
{ "mcp4231-502", MCP423x_502 },
{ "mcp4231-103", MCP423x_103 },
{ "mcp4231-503", MCP423x_503 },
{ "mcp4231-104", MCP423x_104 },
{ "mcp4232-502", MCP423x_502 },
{ "mcp4232-103", MCP423x_103 },
{ "mcp4232-503", MCP423x_503 },
{ "mcp4232-104", MCP423x_104 },
{ "mcp4241-502", MCP424x_502 },
{ "mcp4241-103", MCP424x_103 },
{ "mcp4241-503", MCP424x_503 },
{ "mcp4241-104", MCP424x_104 },
{ "mcp4242-502", MCP424x_502 },
{ "mcp4242-103", MCP424x_103 },
{ "mcp4242-503", MCP424x_503 },
{ "mcp4242-104", MCP424x_104 },
{ "mcp4251-502", MCP425x_502 },
{ "mcp4251-103", MCP425x_103 },
{ "mcp4251-503", MCP425x_503 },
{ "mcp4251-104", MCP425x_104 },
{ "mcp4252-502", MCP425x_502 },
{ "mcp4252-103", MCP425x_103 },
{ "mcp4252-503", MCP425x_503 },
{ "mcp4252-104", MCP425x_104 },
{ "mcp4261-502", MCP426x_502 },
{ "mcp4261-103", MCP426x_103 },
{ "mcp4261-503", MCP426x_503 },
{ "mcp4261-104", MCP426x_104 },
{ "mcp4262-502", MCP426x_502 },
{ "mcp4262-103", MCP426x_103 },
{ "mcp4262-503", MCP426x_503 },
{ "mcp4262-104", MCP426x_104 },
{}
};
MODULE_DEVICE_TABLE(spi, mcp4131_id);
static struct spi_driver mcp4131_driver = {
.driver = {
.name = "mcp4131",
.of_match_table = of_match_ptr(mcp4131_dt_ids),
},
.probe = mcp4131_probe,
.id_table = mcp4131_id,
};
module_spi_driver(mcp4131_driver);
MODULE_AUTHOR("Slawomir Stepien <sst@poczta.fm>");
MODULE_DESCRIPTION("MCP4131 digital potentiometer");
MODULE_LICENSE("GPL v2");
......@@ -79,7 +79,7 @@ static const struct mcp4531_cfg mcp4531_cfg[] = {
struct mcp4531_data {
struct i2c_client *client;
unsigned long devid;
const struct mcp4531_cfg *cfg;
};
#define MCP4531_CHANNEL(ch) { \
......@@ -113,8 +113,8 @@ static int mcp4531_read_raw(struct iio_dev *indio_dev,
*val = ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 1000 * mcp4531_cfg[data->devid].kohms;
*val2 = mcp4531_cfg[data->devid].max_pos;
*val = 1000 * data->cfg->kohms;
*val2 = data->cfg->max_pos;
return IIO_VAL_FRACTIONAL;
}
......@@ -130,7 +130,7 @@ static int mcp4531_write_raw(struct iio_dev *indio_dev,
switch (mask) {
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;
break;
default:
......@@ -152,7 +152,6 @@ static int mcp4531_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
unsigned long devid = id->driver_data;
struct mcp4531_data *data;
struct iio_dev *indio_dev;
......@@ -168,12 +167,12 @@ static int mcp4531_probe(struct i2c_client *client,
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
data->devid = devid;
data->cfg = &mcp4531_cfg[id->driver_data];
indio_dev->dev.parent = dev;
indio_dev->info = &mcp4531_info;
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;
return devm_iio_device_register(dev, indio_dev);
......
......@@ -118,7 +118,7 @@ static int tpl0102_probe(struct i2c_client *client,
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_WORD_DATA))
return -ENOTSUPP;
return -EOPNOTSUPP;
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
if (!indio_dev)
......
......@@ -148,4 +148,14 @@ config T5403
To compile this driver as a module, choose M here: the module
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
......@@ -17,6 +17,7 @@ obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o
st_pressure-y := st_pressure_core.o
st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.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_SPI) += st_pressure_spi.o
/*
* hp206c.c - HOPERF HP206C precision barometer and altimeter sensor
*
* Copyright (c) 2016, Intel Corporation.
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
* (7-bit I2C slave address 0x76)
*
* Datasheet:
* http://www.hoperf.com/upload/sensor/HP206C_DataSheet_EN_V2.0.pdf
*/
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/delay.h>
#include <linux/util_macros.h>
#include <linux/acpi.h>
/* I2C commands: */
#define HP206C_CMD_SOFT_RST 0x06
#define HP206C_CMD_ADC_CVT 0x40
#define HP206C_CMD_ADC_CVT_OSR_4096 0x00
#define HP206C_CMD_ADC_CVT_OSR_2048 0x04
#define HP206C_CMD_ADC_CVT_OSR_1024 0x08
#define HP206C_CMD_ADC_CVT_OSR_512 0x0c
#define HP206C_CMD_ADC_CVT_OSR_256 0x10
#define HP206C_CMD_ADC_CVT_OSR_128 0x14
#define HP206C_CMD_ADC_CVT_CHNL_PT 0x00
#define HP206C_CMD_ADC_CVT_CHNL_T 0x02
#define HP206C_CMD_READ_P 0x30
#define HP206C_CMD_READ_T 0x32
#define HP206C_CMD_READ_REG 0x80
#define HP206C_CMD_WRITE_REG 0xc0
#define HP206C_REG_INT_EN 0x0b
#define HP206C_REG_INT_CFG 0x0c
#define HP206C_REG_INT_SRC 0x0d
#define HP206C_FLAG_DEV_RDY 0x40
#define HP206C_REG_PARA 0x0f
#define HP206C_FLAG_CMPS_EN 0x80
/* Maximum spin for DEV_RDY */
#define HP206C_MAX_DEV_RDY_WAIT_COUNT 20
#define HP206C_DEV_RDY_WAIT_US 20000
struct hp206c_data {
struct mutex mutex;
struct i2c_client *client;
int temp_osr_index;
int pres_osr_index;
};
struct hp206c_osr_setting {
u8 osr_mask;
unsigned int temp_conv_time_us;
unsigned int pres_conv_time_us;
};
/* Data from Table 5 in datasheet. */
static const struct hp206c_osr_setting hp206c_osr_settings[] = {
{ HP206C_CMD_ADC_CVT_OSR_4096, 65600, 131100 },
{ HP206C_CMD_ADC_CVT_OSR_2048, 32800, 65600 },
{ HP206C_CMD_ADC_CVT_OSR_1024, 16400, 32800 },
{ HP206C_CMD_ADC_CVT_OSR_512, 8200, 16400 },
{ HP206C_CMD_ADC_CVT_OSR_256, 4100, 8200 },
{ HP206C_CMD_ADC_CVT_OSR_128, 2100, 4100 },
};
static const int hp206c_osr_rates[] = { 4096, 2048, 1024, 512, 256, 128 };
static const char hp206c_osr_rates_str[] = "4096 2048 1024 512 256 128";
static inline int hp206c_read_reg(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, HP206C_CMD_READ_REG | reg);
}
static inline int hp206c_write_reg(struct i2c_client *client, u8 reg, u8 val)
{
return i2c_smbus_write_byte_data(client,
HP206C_CMD_WRITE_REG | reg, val);
}
static int hp206c_read_20bit(struct i2c_client *client, u8 cmd)
{
int ret;
u8 values[3];
ret = i2c_smbus_read_i2c_block_data(client, cmd, 3, values);
if (ret < 0)
return ret;
if (ret != 3)
return -EIO;
return ((values[0] & 0xF) << 16) | (values[1] << 8) | (values[2]);
}
/* Spin for max 160ms until DEV_RDY is 1, or return error. */
static int hp206c_wait_dev_rdy(struct iio_dev *indio_dev)
{
int ret;
int count = 0;
struct hp206c_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
while (++count <= HP206C_MAX_DEV_RDY_WAIT_COUNT) {
ret = hp206c_read_reg(client, HP206C_REG_INT_SRC);
if (ret < 0) {
dev_err(&indio_dev->dev, "Failed READ_REG INT_SRC: %d\n", ret);
return ret;
}
if (ret & HP206C_FLAG_DEV_RDY)
return 0;
usleep_range(HP206C_DEV_RDY_WAIT_US, HP206C_DEV_RDY_WAIT_US * 3 / 2);
}
return -ETIMEDOUT;
}
static int hp206c_set_compensation(struct i2c_client *client, bool enabled)
{
int val;
val = hp206c_read_reg(client, HP206C_REG_PARA);
if (val < 0)
return val;
if (enabled)
val |= HP206C_FLAG_CMPS_EN;
else
val &= ~HP206C_FLAG_CMPS_EN;
return hp206c_write_reg(client, HP206C_REG_PARA, val);
}
/* Do a soft reset */
static int hp206c_soft_reset(struct iio_dev *indio_dev)
{
int ret;
struct hp206c_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
ret = i2c_smbus_write_byte(client, HP206C_CMD_SOFT_RST);
if (ret) {
dev_err(&client->dev, "Failed to reset device: %d\n", ret);
return ret;
}
usleep_range(400, 600);
ret = hp206c_wait_dev_rdy(indio_dev);
if (ret) {
dev_err(&client->dev, "Device not ready after soft reset: %d\n", ret);
return ret;
}
ret = hp206c_set_compensation(client, true);
if (ret)
dev_err(&client->dev, "Failed to enable compensation: %d\n", ret);
return ret;
}
static int hp206c_conv_and_read(struct iio_dev *indio_dev,
u8 conv_cmd, u8 read_cmd,
unsigned int sleep_us)
{
int ret;
struct hp206c_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
ret = hp206c_wait_dev_rdy(indio_dev);
if (ret < 0) {
dev_err(&indio_dev->dev, "Device not ready: %d\n", ret);
return ret;
}
ret = i2c_smbus_write_byte(client, conv_cmd);
if (ret < 0) {
dev_err(&indio_dev->dev, "Failed convert: %d\n", ret);
return ret;
}
usleep_range(sleep_us, sleep_us * 3 / 2);
ret = hp206c_wait_dev_rdy(indio_dev);
if (ret < 0) {
dev_err(&indio_dev->dev, "Device not ready: %d\n", ret);
return ret;
}
ret = hp206c_read_20bit(client, read_cmd);
if (ret < 0)
dev_err(&indio_dev->dev, "Failed read: %d\n", ret);
return ret;
}
static int hp206c_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
{
int ret;
struct hp206c_data *data = iio_priv(indio_dev);
const struct hp206c_osr_setting *osr_setting;
u8 conv_cmd;
mutex_lock(&data->mutex);
switch (mask) {
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
switch (chan->type) {
case IIO_TEMP:
*val = hp206c_osr_rates[data->temp_osr_index];
ret = IIO_VAL_INT;
break;
case IIO_PRESSURE:
*val = hp206c_osr_rates[data->pres_osr_index];
ret = IIO_VAL_INT;
break;
default:
ret = -EINVAL;
}
break;
case IIO_CHAN_INFO_RAW:
switch (chan->type) {
case IIO_TEMP:
osr_setting = &hp206c_osr_settings[data->temp_osr_index];
conv_cmd = HP206C_CMD_ADC_CVT |
osr_setting->osr_mask |
HP206C_CMD_ADC_CVT_CHNL_T;
ret = hp206c_conv_and_read(indio_dev,
conv_cmd,
HP206C_CMD_READ_T,
osr_setting->temp_conv_time_us);
if (ret >= 0) {
/* 20 significant bits are provided.
* Extend sign over the rest.
*/
*val = sign_extend32(ret, 19);
ret = IIO_VAL_INT;
}
break;
case IIO_PRESSURE:
osr_setting = &hp206c_osr_settings[data->pres_osr_index];
conv_cmd = HP206C_CMD_ADC_CVT |
osr_setting->osr_mask |
HP206C_CMD_ADC_CVT_CHNL_PT;
ret = hp206c_conv_and_read(indio_dev,
conv_cmd,
HP206C_CMD_READ_P,
osr_setting->pres_conv_time_us);
if (ret >= 0) {
*val = ret;
ret = IIO_VAL_INT;
}
break;
default:
ret = -EINVAL;
}
break;
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_TEMP:
*val = 0;
*val2 = 10000;
ret = IIO_VAL_INT_PLUS_MICRO;
break;
case IIO_PRESSURE:
*val = 0;
*val2 = 1000;
ret = IIO_VAL_INT_PLUS_MICRO;
break;
default:
ret = -EINVAL;
}
break;
default:
ret = -EINVAL;
}
mutex_unlock(&data->mutex);
return ret;
}
static int hp206c_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
int ret = 0;
struct hp206c_data *data = iio_priv(indio_dev);
if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO)
return -EINVAL;
mutex_lock(&data->mutex);
switch (chan->type) {
case IIO_TEMP:
data->temp_osr_index = find_closest_descending(val,
hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates));
break;
case IIO_PRESSURE:
data->pres_osr_index = find_closest_descending(val,
hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates));
break;
default:
ret = -EINVAL;
}
mutex_unlock(&data->mutex);
return ret;
}
static const struct iio_chan_spec hp206c_channels[] = {
{
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
},
{
.type = IIO_PRESSURE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
}
};
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(hp206c_osr_rates_str);
static struct attribute *hp206c_attributes[] = {
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
NULL,
};
static const struct attribute_group hp206c_attribute_group = {
.attrs = hp206c_attributes,
};
static const struct iio_info hp206c_info = {
.attrs = &hp206c_attribute_group,
.read_raw = hp206c_read_raw,
.write_raw = hp206c_write_raw,
.driver_module = THIS_MODULE,
};
static int hp206c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct iio_dev *indio_dev;
struct hp206c_data *data;
int ret;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
dev_err(&client->dev, "Adapter does not support "
"all required i2c functionality\n");
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
data->client = client;
mutex_init(&data->mutex);
indio_dev->info = &hp206c_info;
indio_dev->name = id->name;
indio_dev->dev.parent = &client->dev;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = hp206c_channels;
indio_dev->num_channels = ARRAY_SIZE(hp206c_channels);
i2c_set_clientdata(client, indio_dev);
/* Do a soft reset on probe */
ret = hp206c_soft_reset(indio_dev);
if (ret) {
dev_err(&client->dev, "Failed to reset on startup: %d\n", ret);
return -ENODEV;
}
return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct i2c_device_id hp206c_id[] = {
{"hp206c"},
{}
};
#ifdef CONFIG_ACPI
static const struct acpi_device_id hp206c_acpi_match[] = {
{"HOP206C", 0},
{ },
};
MODULE_DEVICE_TABLE(acpi, hp206c_acpi_match);
#endif
static struct i2c_driver hp206c_driver = {
.probe = hp206c_probe,
.id_table = hp206c_id,
.driver = {
.name = "hp206c",
.acpi_match_table = ACPI_PTR(hp206c_acpi_match),
},
};
module_i2c_driver(hp206c_driver);
MODULE_DESCRIPTION("HOPERF HP206C precision barometer and altimeter sensor");
MODULE_AUTHOR("Leonard Crestez <leonard.crestez@intel.com>");
MODULE_LICENSE("GPL v2");
......@@ -16,15 +16,11 @@
#include <linux/iio/iio.h>
#include <linux/mutex.h>
struct regulator;
#define MS5611_RESET 0x1e
#define MS5611_READ_ADC 0x00
#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
enum {
......@@ -39,16 +35,31 @@ struct ms5611_chip_info {
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 {
void *client;
struct mutex lock;
const struct ms5611_osr *pressure_osr;
const struct ms5611_osr *temp_osr;
int (*reset)(struct device *dev);
int (*read_prom_word)(struct device *dev, int index, u16 *word);
int (*read_adc_temp_and_pressure)(struct device *dev,
s32 *temp, s32 *pressure);
struct ms5611_chip_info *chip_info;
struct regulator *vdd;
};
int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
......
......@@ -18,11 +18,44 @@
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.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)
{
int i, j;
......@@ -239,11 +272,70 @@ static int ms5611_read_raw(struct iio_dev *indio_dev,
default:
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;
}
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 struct ms5611_chip_info chip_info_tbl[] = {
......@@ -259,7 +351,8 @@ static const struct iio_chan_spec ms5611_channels[] = {
{
.type = IIO_PRESSURE,
.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_type = {
.sign = 's',
......@@ -271,7 +364,8 @@ static const struct iio_chan_spec ms5611_channels[] = {
{
.type = IIO_TEMP,
.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_type = {
.sign = 's',
......@@ -285,30 +379,53 @@ static const struct iio_chan_spec ms5611_channels[] = {
static const struct iio_info ms5611_info = {
.read_raw = &ms5611_read_raw,
.write_raw = &ms5611_write_raw,
.attrs = &ms5611_attribute_group,
.driver_module = THIS_MODULE,
};
static int ms5611_init(struct iio_dev *indio_dev)
{
int ret;
struct regulator *vdd = devm_regulator_get(indio_dev->dev.parent,
"vdd");
struct ms5611_state *st = iio_priv(indio_dev);
/* Enable attached regulator if any. */
if (!IS_ERR(vdd)) {
ret = regulator_enable(vdd);
st->vdd = devm_regulator_get(indio_dev->dev.parent, "vdd");
if (!IS_ERR(st->vdd)) {
ret = regulator_enable(st->vdd);
if (ret) {
dev_err(indio_dev->dev.parent,
"failed to enable Vdd supply: %d\n", ret);
"failed to enable Vdd supply: %d\n", ret);
return ret;
}
} else {
ret = PTR_ERR(st->vdd);
if (ret != -ENODEV)
return ret;
}
ret = ms5611_reset(indio_dev);
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,
......@@ -319,6 +436,11 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
mutex_init(&st->lock);
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->name = name;
indio_dev->info = &ms5611_info;
......@@ -335,7 +457,7 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
ms5611_trigger_handler, NULL);
if (ret < 0) {
dev_err(dev, "iio triggered buffer setup failed\n");
return ret;
goto err_fini;
}
ret = iio_device_register(indio_dev);
......@@ -348,7 +470,8 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
err_fini:
ms5611_fini(indio_dev);
return ret;
}
EXPORT_SYMBOL(ms5611_probe);
......@@ -357,6 +480,7 @@ int ms5611_remove(struct iio_dev *indio_dev)
{
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
ms5611_fini(indio_dev);
return 0;
}
......
......@@ -17,6 +17,7 @@
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include "ms5611.h"
......@@ -62,23 +63,23 @@ static int ms5611_i2c_read_adc_temp_and_pressure(struct device *dev,
{
int ret;
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)
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);
if (ret < 0)
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)
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);
}
......@@ -113,6 +114,17 @@ static int ms5611_i2c_remove(struct i2c_client *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[] = {
{ "ms5611", MS5611 },
{ "ms5607", MS5607 },
......@@ -123,6 +135,7 @@ MODULE_DEVICE_TABLE(i2c, ms5611_id);
static struct i2c_driver ms5611_driver = {
.driver = {
.name = "ms5611",
.of_match_table = of_match_ptr(ms5611_i2c_matches)
},
.id_table = ms5611_id,
.probe = ms5611_i2c_probe,
......
......@@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/of_device.h>
#include "ms5611.h"
......@@ -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,
s32 *temp, s32 *pressure)
{
u8 cmd;
int ret;
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)
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);
if (ret < 0)
return ret;
cmd = MS5611_START_PRESSURE_CONV;
ret = spi_write_then_read(st->client, &cmd, 1, NULL, 0);
osr = st->pressure_osr;
ret = spi_write_then_read(st->client, &osr->cmd, 1, NULL, 0);
if (ret < 0)
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);
}
......@@ -114,6 +116,17 @@ static int ms5611_spi_remove(struct spi_device *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[] = {
{ "ms5611", MS5611 },
{ "ms5607", MS5607 },
......@@ -124,6 +137,7 @@ MODULE_DEVICE_TABLE(spi, ms5611_id);
static struct spi_driver ms5611_driver = {
.driver = {
.name = "ms5611",
.of_match_table = of_match_ptr(ms5611_spi_matches)
},
.id_table = ms5611_id,
.probe = ms5611_spi_probe,
......
......@@ -27,18 +27,6 @@ config ADIS16203
To compile this driver as a module, say M here: the module will be
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
tristate "Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer"
depends on SPI
......@@ -51,17 +39,6 @@ config ADIS16209
To compile this driver as a module, say M here: the module will be
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
tristate "Analog Devices ADIS16240 Programmable Impact Sensor and Recorder"
depends on SPI
......
......@@ -8,15 +8,9 @@ obj-$(CONFIG_ADIS16201) += adis16201.o
adis16203-y := adis16203_core.o
obj-$(CONFIG_ADIS16203) += adis16203.o
adis16204-y := adis16204_core.o
obj-$(CONFIG_ADIS16204) += adis16204.o
adis16209-y := adis16209_core.o
obj-$(CONFIG_ADIS16209) += adis16209.o
adis16220-y := adis16220_core.o
obj-$(CONFIG_ADIS16220) += adis16220.o
adis16240-y := adis16240_core.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_ */
/*
* ADIS16220 Programmable Digital Vibration Sensor driver
*
* Copyright 2010 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#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/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include "adis16220.h"
static ssize_t adis16220_read_16bit(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct adis16220_state *st = iio_priv(indio_dev);
ssize_t ret;
u16 val;
/* Take the iio_dev status lock */
mutex_lock(&indio_dev->mlock);
ret = adis_read_reg_16(&st->adis, this_attr->address, &val);
mutex_unlock(&indio_dev->mlock);
if (ret)
return ret;
return sprintf(buf, "%u\n", val);
}
static ssize_t adis16220_write_16bit(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct adis16220_state *st = iio_priv(indio_dev);
int ret;
u16 val;
ret = kstrtou16(buf, 10, &val);
if (ret)
goto error_ret;
ret = adis_write_reg_16(&st->adis, this_attr->address, val);
error_ret:
return ret ? ret : len;
}
static int adis16220_capture(struct iio_dev *indio_dev)
{
struct adis16220_state *st = iio_priv(indio_dev);
int ret;
/* initiates a manual data capture */
ret = adis_write_reg_16(&st->adis, ADIS16220_GLOB_CMD, 0xBF08);
if (ret)
dev_err(&indio_dev->dev, "problem beginning capture");
usleep_range(10000, 11000); /* delay for capture to finish */
return ret;
}
static ssize_t adis16220_write_capture(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
bool val;
int ret;
ret = strtobool(buf, &val);
if (ret)
return ret;
if (!val)
return -EINVAL;
ret = adis16220_capture(indio_dev);
if (ret)
return ret;
return len;
}
static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
char *buf,
loff_t off,
size_t count,
int addr)
{
struct adis16220_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[] = {
{
.tx_buf = st->tx,
.bits_per_word = 8,
.len = 2,
.cs_change = 1,
.delay_usecs = 25,
}, {
.tx_buf = st->tx,
.rx_buf = st->rx,
.bits_per_word = 8,
.cs_change = 1,
.delay_usecs = 25,
},
};
int ret;
int i;
if (unlikely(!count))
return count;
if ((off >= ADIS16220_CAPTURE_SIZE) || (count & 1) || (off & 1))
return -EINVAL;
if (off + count > ADIS16220_CAPTURE_SIZE)
count = ADIS16220_CAPTURE_SIZE - off;
/* write the begin position of capture buffer */
ret = adis_write_reg_16(&st->adis,
ADIS16220_CAPT_PNTR,
off > 1);
if (ret)
return -EIO;
/* read count/2 values from capture buffer */
mutex_lock(&st->buf_lock);
for (i = 0; i < count; i += 2) {
st->tx[i] = ADIS_READ_REG(addr);
st->tx[i + 1] = 0;
}
xfers[1].len = count;
ret = spi_sync_transfer(st->adis.spi, xfers, ARRAY_SIZE(xfers));
if (ret) {
mutex_unlock(&st->buf_lock);
return -EIO;
}
memcpy(buf, st->rx, count);
mutex_unlock(&st->buf_lock);
return count;
}
static ssize_t adis16220_accel_bin_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf,
loff_t off,
size_t count)
{
struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj));
return adis16220_capture_buffer_read(indio_dev, buf,
off, count,
ADIS16220_CAPT_BUFA);
}
static struct bin_attribute accel_bin = {
.attr = {
.name = "accel_bin",
.mode = S_IRUGO,
},
.read = adis16220_accel_bin_read,
.size = ADIS16220_CAPTURE_SIZE,
};
static ssize_t adis16220_adc1_bin_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off,
size_t count)
{
struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj));
return adis16220_capture_buffer_read(indio_dev, buf,
off, count,
ADIS16220_CAPT_BUF1);
}
static struct bin_attribute adc1_bin = {
.attr = {
.name = "in0_bin",
.mode = S_IRUGO,
},
.read = adis16220_adc1_bin_read,
.size = ADIS16220_CAPTURE_SIZE,
};
static ssize_t adis16220_adc2_bin_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off,
size_t count)
{
struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj));
return adis16220_capture_buffer_read(indio_dev, buf,
off, count,
ADIS16220_CAPT_BUF2);
}
static struct bin_attribute adc2_bin = {
.attr = {
.name = "in1_bin",
.mode = S_IRUGO,
},
.read = adis16220_adc2_bin_read,
.size = ADIS16220_CAPTURE_SIZE,
};
#define IIO_DEV_ATTR_CAPTURE(_store) \
IIO_DEVICE_ATTR(capture, S_IWUSR, NULL, _store, 0)
static IIO_DEV_ATTR_CAPTURE(adis16220_write_capture);
#define IIO_DEV_ATTR_CAPTURE_COUNT(_mode, _show, _store, _addr) \
IIO_DEVICE_ATTR(capture_count, _mode, _show, _store, _addr)
static IIO_DEV_ATTR_CAPTURE_COUNT(S_IWUSR | S_IRUGO,
adis16220_read_16bit,
adis16220_write_16bit,
ADIS16220_CAPT_PNTR);
enum adis16220_channel {
in_supply, in_1, in_2, accel, temp
};
struct adis16220_address_spec {
u8 addr;
u8 bits;
bool sign;
};
/* Address / bits / signed */
static const struct adis16220_address_spec adis16220_addresses[][3] = {
[in_supply] = { { ADIS16220_CAPT_SUPPLY, 12, 0 }, },
[in_1] = { { ADIS16220_CAPT_BUF1, 16, 1 },
{ ADIS16220_AIN1_NULL, 16, 1 },
{ ADIS16220_CAPT_PEAK1, 16, 1 }, },
[in_2] = { { ADIS16220_CAPT_BUF2, 16, 1 },
{ ADIS16220_AIN2_NULL, 16, 1 },
{ ADIS16220_CAPT_PEAK2, 16, 1 }, },
[accel] = { { ADIS16220_CAPT_BUFA, 16, 1 },
{ ADIS16220_ACCL_NULL, 16, 1 },
{ ADIS16220_CAPT_PEAKA, 16, 1 }, },
[temp] = { { ADIS16220_CAPT_TEMP, 12, 0 }, }
};
static int adis16220_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2,
long mask)
{
struct adis16220_state *st = iio_priv(indio_dev);
const struct adis16220_address_spec *addr;
int ret = -EINVAL;
int addrind = 0;
u16 uval;
s16 sval;
u8 bits;
switch (mask) {
case IIO_CHAN_INFO_RAW:
addrind = 0;
break;
case IIO_CHAN_INFO_OFFSET:
if (chan->type == IIO_TEMP) {
*val = 25000 / -470 - 1278; /* 25 C = 1278 */
return IIO_VAL_INT;
}
addrind = 1;
break;
case IIO_CHAN_INFO_PEAK:
addrind = 2;
break;
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_TEMP:
*val = -470; /* -0.47 C */
*val2 = 0;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_ACCEL:
*val2 = IIO_G_TO_M_S_2(19073); /* 19.073 g */
return IIO_VAL_INT_PLUS_MICRO;
case IIO_VOLTAGE:
if (chan->channel == 0) {
*val = 1;
*val2 = 220700; /* 1.2207 mV */
} else {
/* Should really be dependent on VDD */
*val2 = 305180; /* 305.18 uV */
}
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
default:
return -EINVAL;
}
addr = &adis16220_addresses[chan->address][addrind];
if (addr->sign) {
ret = adis_read_reg_16(&st->adis, addr->addr, &sval);
if (ret)
return ret;
bits = addr->bits;
sval &= (1 << bits) - 1;
sval = (s16)(sval << (16 - bits)) >> (16 - bits);
*val = sval;
return IIO_VAL_INT;
}
ret = adis_read_reg_16(&st->adis, addr->addr, &uval);
if (ret)
return ret;
bits = addr->bits;
uval &= (1 << bits) - 1;
*val = uval;
return IIO_VAL_INT;
}
static const struct iio_chan_spec adis16220_channels[] = {
{
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
.extend_name = "supply",
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.address = in_supply,
}, {
.type = IIO_ACCEL,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_PEAK),
.address = accel,
}, {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE),
.address = temp,
}, {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE),
.address = in_1,
}, {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 2,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.address = in_2,
}
};
static struct attribute *adis16220_attributes[] = {
&iio_dev_attr_capture.dev_attr.attr,
&iio_dev_attr_capture_count.dev_attr.attr,
NULL
};
static const struct attribute_group adis16220_attribute_group = {
.attrs = adis16220_attributes,
};
static const struct iio_info adis16220_info = {
.attrs = &adis16220_attribute_group,
.driver_module = THIS_MODULE,
.read_raw = &adis16220_read_raw,
};
static const char * const adis16220_status_error_msgs[] = {
[ADIS16220_DIAG_STAT_VIOLATION_BIT] = "Capture period violation/interruption",
[ADIS16220_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
[ADIS16220_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
[ADIS16220_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
[ADIS16220_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V",
};
static const struct adis_data adis16220_data = {
.read_delay = 35,
.write_delay = 35,
.msc_ctrl_reg = ADIS16220_MSC_CTRL,
.glob_cmd_reg = ADIS16220_GLOB_CMD,
.diag_stat_reg = ADIS16220_DIAG_STAT,
.self_test_mask = ADIS16220_MSC_CTRL_SELF_TEST_EN,
.startup_delay = ADIS16220_STARTUP_DELAY,
.status_error_msgs = adis16220_status_error_msgs,
.status_error_mask = BIT(ADIS16220_DIAG_STAT_VIOLATION_BIT) |
BIT(ADIS16220_DIAG_STAT_SPI_FAIL_BIT) |
BIT(ADIS16220_DIAG_STAT_FLASH_UPT_BIT) |
BIT(ADIS16220_DIAG_STAT_POWER_HIGH_BIT) |
BIT(ADIS16220_DIAG_STAT_POWER_LOW_BIT),
};
static int adis16220_probe(struct spi_device *spi)
{
int ret;
struct adis16220_state *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 = &adis16220_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = adis16220_channels;
indio_dev->num_channels = ARRAY_SIZE(adis16220_channels);
ret = devm_iio_device_register(&spi->dev, indio_dev);
if (ret)
return ret;
ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &accel_bin);
if (ret)
return ret;
ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc1_bin);
if (ret)
goto error_rm_accel_bin;
ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc2_bin);
if (ret)
goto error_rm_adc1_bin;
ret = adis_init(&st->adis, indio_dev, spi, &adis16220_data);
if (ret)
goto error_rm_adc2_bin;
/* Get the device into a sane initial state */
ret = adis_initial_startup(&st->adis);
if (ret)
goto error_rm_adc2_bin;
return 0;
error_rm_adc2_bin:
sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin);
error_rm_adc1_bin:
sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin);
error_rm_accel_bin:
sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin);
return ret;
}
static int adis16220_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin);
sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin);
sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin);
return 0;
}
static struct spi_driver adis16220_driver = {
.driver = {
.name = "adis16220",
},
.probe = adis16220_probe,
.remove = adis16220_remove,
};
module_spi_driver(adis16220_driver);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADIS16220 Digital Vibration Sensor");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:adis16220");
......@@ -349,11 +349,9 @@ static ssize_t ad7192_write_frequency(struct device *dev,
if (lval == 0)
return -EINVAL;
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev)) {
mutex_unlock(&indio_dev->mlock);
return -EBUSY;
}
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
div = st->mclk / (lval * st->f_order * 1024);
if (div < 1 || div > 1023) {
......@@ -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);
out:
mutex_unlock(&indio_dev->mlock);
iio_device_release_direct_mode(indio_dev);
return ret ? ret : len;
}
......@@ -434,11 +432,9 @@ static ssize_t ad7192_set(struct device *dev,
if (ret < 0)
return ret;
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev)) {
mutex_unlock(&indio_dev->mlock);
return -EBUSY;
}
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
switch ((u32)this_attr->address) {
case AD7192_REG_GPOCON:
......@@ -461,7 +457,7 @@ static ssize_t ad7192_set(struct device *dev,
ret = -EINVAL;
}
mutex_unlock(&indio_dev->mlock);
iio_device_release_direct_mode(indio_dev);
return ret ? ret : len;
}
......@@ -555,11 +551,9 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
int ret, i;
unsigned int tmp;
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev)) {
mutex_unlock(&indio_dev->mlock);
return -EBUSY;
}
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
switch (mask) {
case IIO_CHAN_INFO_SCALE:
......@@ -582,7 +576,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
ret = -EINVAL;
}
mutex_unlock(&indio_dev->mlock);
iio_device_release_direct_mode(indio_dev);
return ret;
}
......
......@@ -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;
......@@ -165,7 +165,7 @@ static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned val)
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);
......@@ -191,7 +191,7 @@ static void ad7280_delay(struct ad7280_state *st)
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;
struct spi_transfer t = {
......@@ -211,10 +211,10 @@ static int __ad7280_read32(struct ad7280_state *st, unsigned *val)
return 0;
}
static int ad7280_write(struct ad7280_state *st, unsigned devaddr,
unsigned addr, bool all, unsigned val)
static int ad7280_write(struct ad7280_state *st, unsigned int devaddr,
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;
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,
return spi_write(st->spi, &st->buf[0], 4);
}
static int ad7280_read(struct ad7280_state *st, unsigned devaddr,
unsigned addr)
static int ad7280_read(struct ad7280_state *st, unsigned int devaddr,
unsigned int addr)
{
int ret;
unsigned tmp;
unsigned int tmp;
/* turns off the read operation on all parts */
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,
return (tmp >> 13) & 0xFF;
}
static int ad7280_read_channel(struct ad7280_state *st, unsigned devaddr,
unsigned addr)
static int ad7280_read_channel(struct ad7280_state *st, unsigned int devaddr,
unsigned int addr)
{
int ret;
unsigned tmp;
unsigned int tmp;
ret = ad7280_write(st, devaddr, AD7280A_READ, 0, addr << 2);
if (ret)
......@@ -299,11 +299,11 @@ static int ad7280_read_channel(struct ad7280_state *st, unsigned devaddr,
return (tmp >> 11) & 0xFFF;
}
static int ad7280_read_all_channels(struct ad7280_state *st, unsigned cnt,
unsigned *array)
static int ad7280_read_all_channels(struct ad7280_state *st, unsigned int cnt,
unsigned int *array)
{
int i, ret;
unsigned tmp, sum = 0;
unsigned int tmp, sum = 0;
ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ, 1,
AD7280A_CELL_VOLTAGE_1 << 2);
......@@ -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)
{
unsigned val, n;
unsigned int val, n;
int ret;
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,
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
bool readin;
int ret;
unsigned devaddr, ch;
unsigned int devaddr, ch;
ret = strtobool(buf, &readin);
if (ret)
......@@ -431,7 +431,7 @@ static ssize_t ad7280_show_balance_timer(struct device *dev,
struct ad7280_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
unsigned msecs;
unsigned int msecs;
mutex_lock(&indio_dev->mlock);
ret = ad7280_read(st, this_attr->address >> 8,
......@@ -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 ad7280_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
unsigned val;
unsigned int val;
switch ((u32)this_attr->address) {
case AD7280A_CELL_OVERVOLTAGE:
......@@ -683,7 +683,7 @@ static irqreturn_t ad7280_event_handler(int irq, void *private)
{
struct iio_dev *indio_dev = private;
struct ad7280_state *st = iio_priv(indio_dev);
unsigned *channels;
unsigned int *channels;
int i, ret;
channels = kcalloc(st->scan_cnt, sizeof(*channels), GFP_KERNEL);
......
......@@ -29,10 +29,10 @@
#define AD7280A_ALERT_REMOVE_AUX4_AUX5 BIT(1)
struct ad7280_platform_data {
unsigned acquisition_time;
unsigned conversion_averaging;
unsigned chain_last_alert_ignore;
bool thermistor_term_en;
unsigned int acquisition_time;
unsigned int conversion_averaging;
unsigned int chain_last_alert_ignore;
bool thermistor_term_en;
};
#endif /* IIO_ADC_AD7280_H_ */
......@@ -28,16 +28,16 @@
*/
struct ad7606_platform_data {
unsigned default_os;
unsigned default_range;
unsigned gpio_convst;
unsigned gpio_reset;
unsigned gpio_range;
unsigned gpio_os0;
unsigned gpio_os1;
unsigned gpio_os2;
unsigned gpio_frstdata;
unsigned gpio_stby;
unsigned int default_os;
unsigned int default_range;
unsigned int gpio_convst;
unsigned int gpio_reset;
unsigned int gpio_range;
unsigned int gpio_os0;
unsigned int gpio_os1;
unsigned int gpio_os2;
unsigned int gpio_frstdata;
unsigned int gpio_stby;
};
/**
......@@ -52,7 +52,7 @@ struct ad7606_chip_info {
const char *name;
u16 int_vref_mv;
const struct iio_chan_spec *channels;
unsigned num_channels;
unsigned int num_channels;
};
/**
......@@ -67,8 +67,8 @@ struct ad7606_state {
struct work_struct poll_work;
wait_queue_head_t wq_data_avail;
const struct ad7606_bus_ops *bops;
unsigned range;
unsigned oversampling;
unsigned int range;
unsigned int oversampling;
bool done;
void __iomem *base_address;
......@@ -86,7 +86,7 @@ struct ad7606_bus_ops {
};
struct iio_dev *ad7606_probe(struct device *dev, int irq,
void __iomem *base_address, unsigned id,
void __iomem *base_address, unsigned int id,
const struct ad7606_bus_ops *bops);
int ad7606_remove(struct iio_dev *indio_dev, int irq);
int ad7606_reset(struct ad7606_state *st);
......
......@@ -36,7 +36,7 @@ int ad7606_reset(struct ad7606_state *st)
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);
int ret;
......@@ -155,7 +155,7 @@ static ssize_t ad7606_show_oversampling_ratio(struct device *dev,
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};
int i;
......@@ -446,7 +446,7 @@ static const struct iio_info ad7606_info_range = {
struct iio_dev *ad7606_probe(struct device *dev, int irq,
void __iomem *base_address,
unsigned id,
unsigned int id,
const struct ad7606_bus_ops *bops)
{
struct ad7606_platform_data *pdata = dev->platform_data;
......
......@@ -63,7 +63,7 @@ static int ad7780_set_mode(struct ad_sigma_delta *sigma_delta,
enum ad_sigma_delta_mode mode)
{
struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta);
unsigned val;
unsigned int val;
switch (mode) {
case AD_SD_MODE_SINGLE:
......
......@@ -101,14 +101,14 @@ struct ad5933_state {
unsigned long mclk_hz;
unsigned char ctrl_hb;
unsigned char ctrl_lb;
unsigned range_avail[4];
unsigned int range_avail[4];
unsigned short vref_mv;
unsigned short settling_cycles;
unsigned short freq_points;
unsigned freq_start;
unsigned freq_inc;
unsigned state;
unsigned poll_time_jiffies;
unsigned int freq_start;
unsigned int freq_inc;
unsigned int state;
unsigned int poll_time_jiffies;
};
static struct ad5933_platform_data ad5933_default_pdata = {
......@@ -222,7 +222,7 @@ static int ad5933_wait_busy(struct ad5933_state *st, unsigned char event)
}
static int ad5933_set_freq(struct ad5933_state *st,
unsigned reg, unsigned long freq)
unsigned int reg, unsigned long freq)
{
unsigned long long freqreg;
union {
......@@ -282,7 +282,7 @@ static int ad5933_setup(struct ad5933_state *st)
static void ad5933_calc_out_ranges(struct ad5933_state *st)
{
int i;
unsigned normalized_3v3[4] = {1980, 198, 383, 970};
unsigned int normalized_3v3[4] = {1980, 198, 383, 970};
for (i = 0; i < 4; i++)
st->range_avail[i] = normalized_3v3[i] * st->vref_mv / 3300;
......
......@@ -69,7 +69,6 @@ enum als_ir_mode {
};
struct isl29028_chip {
struct device *dev;
struct mutex lock;
struct regmap *regmap;
......@@ -166,20 +165,21 @@ static int isl29028_set_als_ir_mode(struct isl29028_chip *chip,
static int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir)
{
struct device *dev = regmap_get_device(chip->regmap);
unsigned int lsb;
unsigned int msb;
int ret;
ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_L, &lsb);
if (ret < 0) {
dev_err(chip->dev,
dev_err(dev,
"Error in reading register ALSIR_L err %d\n", ret);
return ret;
}
ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_U, &msb);
if (ret < 0) {
dev_err(chip->dev,
dev_err(dev,
"Error in reading register ALSIR_U err %d\n", ret);
return ret;
}
......@@ -190,12 +190,13 @@ static int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir)
static int isl29028_read_proxim(struct isl29028_chip *chip, int *prox)
{
struct device *dev = regmap_get_device(chip->regmap);
unsigned int data;
int ret;
ret = regmap_read(chip->regmap, ISL29028_REG_PROX_DATA, &data);
if (ret < 0) {
dev_err(chip->dev, "Error in reading register %d, error %d\n",
dev_err(dev, "Error in reading register %d, error %d\n",
ISL29028_REG_PROX_DATA, ret);
return ret;
}
......@@ -218,13 +219,14 @@ static int isl29028_proxim_get(struct isl29028_chip *chip, int *prox_data)
static int isl29028_als_get(struct isl29028_chip *chip, int *als_data)
{
struct device *dev = regmap_get_device(chip->regmap);
int ret;
int als_ir_data;
if (chip->als_ir_mode != MODE_ALS) {
ret = isl29028_set_als_ir_mode(chip, MODE_ALS);
if (ret < 0) {
dev_err(chip->dev,
dev_err(dev,
"Error in enabling ALS mode err %d\n", ret);
return ret;
}
......@@ -251,12 +253,13 @@ static int isl29028_als_get(struct isl29028_chip *chip, int *als_data)
static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data)
{
struct device *dev = regmap_get_device(chip->regmap);
int ret;
if (chip->als_ir_mode != MODE_IR) {
ret = isl29028_set_als_ir_mode(chip, MODE_IR);
if (ret < 0) {
dev_err(chip->dev,
dev_err(dev,
"Error in enabling IR mode err %d\n", ret);
return ret;
}
......@@ -271,25 +274,26 @@ static int isl29028_write_raw(struct iio_dev *indio_dev,
int val, int val2, long mask)
{
struct isl29028_chip *chip = iio_priv(indio_dev);
struct device *dev = regmap_get_device(chip->regmap);
int ret = -EINVAL;
mutex_lock(&chip->lock);
switch (chan->type) {
case IIO_PROXIMITY:
if (mask != IIO_CHAN_INFO_SAMP_FREQ) {
dev_err(chip->dev,
dev_err(dev,
"proximity: mask value 0x%08lx not supported\n",
mask);
break;
}
if (val < 1 || val > 100) {
dev_err(chip->dev,
dev_err(dev,
"Samp_freq %d is not in range[1:100]\n", val);
break;
}
ret = isl29028_set_proxim_sampling(chip, val);
if (ret < 0) {
dev_err(chip->dev,
dev_err(dev,
"Setting proximity samp_freq fail, err %d\n",
ret);
break;
......@@ -299,19 +303,19 @@ static int isl29028_write_raw(struct iio_dev *indio_dev,
case IIO_LIGHT:
if (mask != IIO_CHAN_INFO_SCALE) {
dev_err(chip->dev,
dev_err(dev,
"light: mask value 0x%08lx not supported\n",
mask);
break;
}
if ((val != 125) && (val != 2000)) {
dev_err(chip->dev,
dev_err(dev,
"lux scale %d is invalid [125, 2000]\n", val);
break;
}
ret = isl29028_set_als_scale(chip, val);
if (ret < 0) {
dev_err(chip->dev,
dev_err(dev,
"Setting lux scale fail with error %d\n", ret);
break;
}
......@@ -319,7 +323,7 @@ static int isl29028_write_raw(struct iio_dev *indio_dev,
break;
default:
dev_err(chip->dev, "Unsupported channel type\n");
dev_err(dev, "Unsupported channel type\n");
break;
}
mutex_unlock(&chip->lock);
......@@ -331,6 +335,7 @@ static int isl29028_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct isl29028_chip *chip = iio_priv(indio_dev);
struct device *dev = regmap_get_device(chip->regmap);
int ret = -EINVAL;
mutex_lock(&chip->lock);
......@@ -370,7 +375,7 @@ static int isl29028_read_raw(struct iio_dev *indio_dev,
break;
default:
dev_err(chip->dev, "mask value 0x%08lx not supported\n", mask);
dev_err(dev, "mask value 0x%08lx not supported\n", mask);
break;
}
mutex_unlock(&chip->lock);
......@@ -417,6 +422,7 @@ static const struct iio_info isl29028_info = {
static int isl29028_chip_init(struct isl29028_chip *chip)
{
struct device *dev = regmap_get_device(chip->regmap);
int ret;
chip->enable_prox = false;
......@@ -426,35 +432,33 @@ static int isl29028_chip_init(struct isl29028_chip *chip)
ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0);
if (ret < 0) {
dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n",
dev_err(dev, "%s(): write to reg %d failed, err = %d\n",
__func__, ISL29028_REG_TEST1_MODE, ret);
return ret;
}
ret = regmap_write(chip->regmap, ISL29028_REG_TEST2_MODE, 0x0);
if (ret < 0) {
dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n",
dev_err(dev, "%s(): write to reg %d failed, err = %d\n",
__func__, ISL29028_REG_TEST2_MODE, ret);
return ret;
}
ret = regmap_write(chip->regmap, ISL29028_REG_CONFIGURE, 0x0);
if (ret < 0) {
dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n",
dev_err(dev, "%s(): write to reg %d failed, err = %d\n",
__func__, ISL29028_REG_CONFIGURE, ret);
return ret;
}
ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling);
if (ret < 0) {
dev_err(chip->dev, "setting the proximity, err = %d\n",
ret);
dev_err(dev, "setting the proximity, err = %d\n", ret);
return ret;
}
ret = isl29028_set_als_scale(chip, chip->lux_scale);
if (ret < 0)
dev_err(chip->dev,
"setting als scale failed, err = %d\n", ret);
dev_err(dev, "setting als scale failed, err = %d\n", ret);
return ret;
}
......@@ -496,19 +500,19 @@ static int isl29028_probe(struct i2c_client *client,
chip = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
chip->dev = &client->dev;
mutex_init(&chip->lock);
chip->regmap = devm_regmap_init_i2c(client, &isl29028_regmap_config);
if (IS_ERR(chip->regmap)) {
ret = PTR_ERR(chip->regmap);
dev_err(chip->dev, "regmap initialization failed: %d\n", ret);
dev_err(&client->dev, "regmap initialization failed: %d\n",
ret);
return ret;
}
ret = isl29028_chip_init(chip);
if (ret < 0) {
dev_err(chip->dev, "chip initialization failed: %d\n", ret);
dev_err(&client->dev, "chip initialization failed: %d\n", ret);
return ret;
}
......@@ -520,7 +524,8 @@ static int isl29028_probe(struct i2c_client *client,
indio_dev->modes = INDIO_DIRECT_MODE;
ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
if (ret < 0) {
dev_err(chip->dev, "iio registration fails with error %d\n",
dev_err(&client->dev,
"iio registration fails with error %d\n",
ret);
return ret;
}
......
......@@ -33,7 +33,7 @@ static int ade7758_spi_read_burst(struct iio_dev *indio_dev)
return ret;
}
static int ade7758_write_waveform_type(struct device *dev, unsigned type)
static int ade7758_write_waveform_type(struct device *dev, unsigned int type)
{
int ret;
u8 reg;
......@@ -85,7 +85,7 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p)
**/
static int ade7758_ring_preenable(struct iio_dev *indio_dev)
{
unsigned channel;
unsigned int channel;
if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
return -EINVAL;
......
......@@ -12,9 +12,9 @@
#define _AD2S1210_H
struct ad2s1210_platform_data {
unsigned sample;
unsigned a[2];
unsigned res[2];
bool gpioin;
unsigned int sample;
unsigned int a[2];
unsigned int res[2];
bool gpioin;
};
#endif /* _AD2S1210_H */
......@@ -55,12 +55,12 @@ static struct bfin_timer iio_bfin_timer_code[MAX_BLACKFIN_GPTIMERS] = {
};
struct bfin_tmr_state {
struct iio_trigger *trig;
struct bfin_timer *t;
unsigned timer_num;
bool output_enable;
unsigned int duty;
int irq;
struct iio_trigger *trig;
struct bfin_timer *t;
unsigned int timer_num;
bool output_enable;
unsigned int duty;
int irq;
};
static int iio_bfin_tmr_set_state(struct iio_trigger *trig, bool state)
......
......@@ -83,10 +83,12 @@ struct iio_buffer_access_funcs {
* @access: [DRIVER] buffer access functions associated with the
* implementation.
* @scan_el_dev_attr_list:[INTERN] list of scan element related attributes.
* @buffer_group: [INTERN] attributes of the buffer group
* @scan_el_group: [DRIVER] attribute group for those attributes not
* created from the iio_chan_info array.
* @pollq: [INTERN] wait queue to allow for polling on the buffer.
* @stufftoread: [INTERN] flag to indicate new data.
* @attrs: [INTERN] standard attributes of the buffer
* @demux_list: [INTERN] list of operations required to demux the scan.
* @demux_bounce: [INTERN] buffer for doing gather from incoming scan.
* @buffer_list: [INTERN] entry in the devices list of current buffers.
......
......@@ -527,6 +527,8 @@ void iio_device_unregister(struct iio_dev *indio_dev);
int devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev);
void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev);
int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp);
int iio_device_claim_direct_mode(struct iio_dev *indio_dev);
void iio_device_release_direct_mode(struct iio_dev *indio_dev);
extern struct bus_type iio_bus_type;
......
......@@ -38,6 +38,7 @@ enum iio_chan_type {
IIO_CONCENTRATION,
IIO_RESISTANCE,
IIO_PH,
IIO_UVINDEX,
};
enum iio_modifier {
......@@ -77,6 +78,7 @@ enum iio_modifier {
IIO_MOD_Q,
IIO_MOD_CO2,
IIO_MOD_VOC,
IIO_MOD_LIGHT_UV,
};
enum iio_event_type {
......
......@@ -304,7 +304,19 @@ int main(int argc, char **argv)
}
}
/* Verify the trigger exists */
/* Look for this "-devN" trigger */
trig_num = find_type_by_name(trigger_name, "trigger");
if (trig_num < 0) {
/* OK try the simpler "-trigger" suffix instead */
free(trigger_name);
ret = asprintf(&trigger_name,
"%s-trigger", device_name);
if (ret < 0) {
ret = -ENOMEM;
goto error_free_dev_dir_name;
}
}
trig_num = find_type_by_name(trigger_name, "trigger");
if (trig_num < 0) {
fprintf(stderr, "Failed to find the trigger %s\n",
......
......@@ -53,6 +53,10 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_ENERGY] = "energy",
[IIO_DISTANCE] = "distance",
[IIO_VELOCITY] = "velocity",
[IIO_CONCENTRATION] = "concentration",
[IIO_RESISTANCE] = "resistance",
[IIO_PH] = "ph",
[IIO_UVINDEX] = "uvindex",
};
static const char * const iio_ev_type_text[] = {
......@@ -90,6 +94,7 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_LIGHT_RED] = "red",
[IIO_MOD_LIGHT_GREEN] = "green",
[IIO_MOD_LIGHT_BLUE] = "blue",
[IIO_MOD_LIGHT_UV] = "uv",
[IIO_MOD_QUATERNION] = "quaternion",
[IIO_MOD_TEMP_AMBIENT] = "ambient",
[IIO_MOD_TEMP_OBJECT] = "object",
......@@ -102,6 +107,10 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_WALKING] = "walking",
[IIO_MOD_STILL] = "still",
[IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)",
[IIO_MOD_I] = "i",
[IIO_MOD_Q] = "q",
[IIO_MOD_CO2] = "co2",
[IIO_MOD_VOC] = "voc",
};
static bool event_is_known(struct iio_event_data *event)
......@@ -136,6 +145,10 @@ static bool event_is_known(struct iio_event_data *event)
case IIO_ENERGY:
case IIO_DISTANCE:
case IIO_VELOCITY:
case IIO_CONCENTRATION:
case IIO_RESISTANCE:
case IIO_PH:
case IIO_UVINDEX:
break;
default:
return false;
......@@ -162,6 +175,7 @@ static bool event_is_known(struct iio_event_data *event)
case IIO_MOD_LIGHT_RED:
case IIO_MOD_LIGHT_GREEN:
case IIO_MOD_LIGHT_BLUE:
case IIO_MOD_LIGHT_UV:
case IIO_MOD_QUATERNION:
case IIO_MOD_TEMP_AMBIENT:
case IIO_MOD_TEMP_OBJECT:
......@@ -174,6 +188,10 @@ static bool event_is_known(struct iio_event_data *event)
case IIO_MOD_WALKING:
case IIO_MOD_STILL:
case IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z:
case IIO_MOD_I:
case IIO_MOD_Q:
case IIO_MOD_CO2:
case IIO_MOD_VOC:
break;
default:
return false;
......
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