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

Merge tag 'iio-for-4.12c' of...

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

Third set of new device support, cleanups and features for IIO in the 4.12 cycle

Somewhat dominated in patch numbers of last of the outreachy application
window related patches (they are still coming, despite window being closed
which is good to see!)

Good set of new drivers as well.

New device support
* ASPEED ADC
  - new driver
* cpcap PMIC ADC
  - new driver
* hid-humidity
  - driver for HID compatible humidity sensors.
* ltc2497 ADC
  - new driver
* mpu6050
  - bring bindings up to date and add trivial support for 9250
* rockchip-saradc
  - update bindings to cover rk3328
* vl6180 light, proximity and time of flight sensor.
  - new driver

Features
* meson-saradc
  - add calibration

Cleanup and minor fixes
* ad5504
  - constify attribute_group structure
  - drop casting of void *
* ad7150
  - replace some shifts of 1 by BIT macro usage
* ad7152
  - blank lines between function definitions
* ad7280a
  - octal permissions.
* ad7606
  - replace use of core mlock mutex with a local lock
* ad7746
  - replace some shifts of 1 by BIT macro usage
  - function parameter alignment
  - drop some excessive brackets (introduced in last pull request)
* ad7753
  - white space cleanup
* ad7754
  - includes in alphabetical order and groupped appropriately.
  - change from missuse of internal mlock mutex to using the buffer lock to
  also protect values during frequency update.
* ad779x
  - constify attribute_group structures
* ad9832
  - octal permissions
* adis16060
  - remove use of core mlock mutex in favour of adding a local
  _spi_write_then_read which can use the local buffer protection lock.
  - fix naming of above function.
* adis16203
  - remove locking during reads of calibbias that doesn't protect anything
  not protected elsewhere.
* adis16209
  - remove unnecessary braces in single statement if
* adis16240
  - remove unnecessary braces in single statement if
* adt7136
  - drop excess blank lines and put some in between functions.
* ams-iaq
  - replace comma with semi colon. Not actual bug, just unusual syntax.
* apds9960
  - constify attribute group structure
* as3935
  - constify attribute group structure
* bm1750
  - constify attribute group structure
* cros_ec
  - devm version of triggered buffer setup to simplify code.
* exynos
  - drop casting of void *
* hdc100x
  - constify attribute_group structure
* hid-accel
  - fix wrong scale for newly introduced gravity sensor.
* hts221
  - drop casting of void *
* hx711
  - constify attribute_group structure
* imx7d_adc
  - drop casting of void *
* lm35333
  - constify attribute_group structure
* lsm6dsx
  - drop casting of void *
  - hold ODR configuration until enabling to avoid a race condition.
* max1027
  - drop casting of void *
* max11100
  - fix a comma where semicolon was intended (no actual bug, just odd)
* max1363
  - constify attribute_group structure
* ms sensors
  - drop casting of void *
* rockchip_saradc
  - drop casting of void *
* sun4i-gpadc
  - fix missing dependency on THERMAL or presence of stubs (issue only
  introduced in pervious set)
  - drop casting of void *
* tsl2x7x
  - fix wrong standard deviation calc.  Note these aren't actually used for
  anything at the moment so bug didn't really matter.
  - constify attribute group structure.
* vf610adc
  - drop casting of void *
* vz89x
  - replace comma with semicolon. Not actual bug, just odd syntax.
* zpa2326
  - drop casting of void *
parents a2e99e97 2ccc1503
Aspeed ADC
This device is a 10-bit converter for 16 voltage channels. All inputs are
single ended.
Required properties:
- compatible: Should be "aspeed,ast2400-adc" or "aspeed,ast2500-adc"
- reg: memory window mapping address and length
- clocks: Input clock used to derive the sample clock. Expected to be the
SoC's APB clock.
- #io-channel-cells: Must be set to <1> to indicate channels are selected
by index.
Example:
adc@1e6e9000 {
compatible = "aspeed,ast2400-adc";
reg = <0x1e6e9000 0xb0>;
clocks = <&clk_apb>;
#io-channel-cells = <1>;
};
Motorola CPCAP PMIC ADC binding
Required properties:
- compatible: Should be "motorola,cpcap-adc" or "motorola,mapphone-cpcap-adc"
- interrupt-parent: The interrupt controller
- interrupts: The interrupt number for the ADC device
- interrupt-names: Should be "adcdone"
- #io-channel-cells: Number of cells in an IIO specifier
Example:
cpcap_adc: adc {
compatible = "motorola,mapphone-cpcap-adc";
interrupt-parent = <&cpcap>;
interrupts = <8 IRQ_TYPE_NONE>;
interrupt-names = "adcdone";
#io-channel-cells = <1>;
};
* Linear Technology / Analog Devices LTC2497 ADC
Required properties:
- compatible: Must be "lltc,ltc2497"
- reg: Must contain the ADC I2C address
- vref-supply: The regulator supply for ADC reference voltage
Example:
ltc2497: adc@76 {
compatible = "lltc,ltc2497";
reg = <0x76>;
vref-supply = <&ltc2497_reg>;
};
...@@ -4,6 +4,7 @@ Required properties: ...@@ -4,6 +4,7 @@ Required properties:
- compatible: should be "rockchip,<name>-saradc" or "rockchip,rk3066-tsadc" - compatible: should be "rockchip,<name>-saradc" or "rockchip,rk3066-tsadc"
- "rockchip,saradc": for rk3188, rk3288 - "rockchip,saradc": for rk3188, rk3288
- "rockchip,rk3066-tsadc": for rk3036 - "rockchip,rk3066-tsadc": for rk3036
- "rockchip,rk3328-saradc", "rockchip,rk3399-saradc": for rk3328
- "rockchip,rk3399-saradc": for rk3399 - "rockchip,rk3399-saradc": for rk3399
- reg: physical base address of the controller and length of memory mapped - reg: physical base address of the controller and length of memory mapped
......
...@@ -3,14 +3,21 @@ InvenSense MPU-6050 Six-Axis (Gyro + Accelerometer) MEMS MotionTracking Device ...@@ -3,14 +3,21 @@ InvenSense MPU-6050 Six-Axis (Gyro + Accelerometer) MEMS MotionTracking Device
http://www.invensense.com/mems/gyro/mpu6050.html http://www.invensense.com/mems/gyro/mpu6050.html
Required properties: Required properties:
- compatible : should be "invensense,mpu6050" - compatible : should be one of
"invensense,mpu6050"
"invensense,mpu6500"
"invensense,mpu9150"
"invensense,mpu9250"
"invensense,icm20608"
- reg : the I2C address of the sensor - reg : the I2C address of the sensor
- interrupt-parent : should be the phandle for the interrupt controller - interrupt-parent : should be the phandle for the interrupt controller
- interrupts : interrupt mapping for GPIO IRQ - interrupts : interrupt mapping for GPIO IRQ
Optional properties: Optional properties:
- mount-matrix: an optional 3x3 mounting rotation matrix - mount-matrix: an optional 3x3 mounting rotation matrix
- i2c-gate node. These devices also support an auxiliary i2c bus. This is
simple enough to be described using the i2c-gate binding. See
i2c/i2c-gate.txt for more details.
Example: Example:
mpu6050@68 { mpu6050@68 {
...@@ -28,3 +35,19 @@ Example: ...@@ -28,3 +35,19 @@ Example:
"0", /* y2 */ "0", /* y2 */
"0.984807753012208"; /* z2 */ "0.984807753012208"; /* z2 */
}; };
mpu9250@68 {
compatible = "invensense,mpu9250";
reg = <0x68>;
interrupt-parent = <&gpio3>;
interrupts = <21 1>;
i2c-gate {
#address-cells = <1>;
#size-cells = <0>;
ax8975@c {
compatible = "ak,ak8975";
reg = <0x0c>;
};
};
};
STMicro VL6180 - ALS, range and proximity sensor
Link to datasheet: http://www.st.com/resource/en/datasheet/vl6180x.pdf
Required properties:
-compatible: should be "st,vl6180"
-reg: the I2C address of the sensor
Example:
vl6180@29 {
compatible = "st,vl6180";
reg = <0x29>;
};
...@@ -813,6 +813,7 @@ W: http://wiki.analog.com/ ...@@ -813,6 +813,7 @@ W: http://wiki.analog.com/
W: http://ez.analog.com/community/linux-device-drivers W: http://ez.analog.com/community/linux-device-drivers
S: Supported S: Supported
F: drivers/iio/*/ad* F: drivers/iio/*/ad*
F: drivers/iio/adc/ltc2497*
X: drivers/iio/*/adjd* X: drivers/iio/*/adjd*
F: drivers/staging/iio/*/ad* F: drivers/staging/iio/*/ad*
F: drivers/staging/iio/trigger/iio-trig-bfin-timer.c F: drivers/staging/iio/trigger/iio-trig-bfin-timer.c
......
...@@ -130,6 +130,17 @@ config AD799X ...@@ -130,6 +130,17 @@ config AD799X
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called ad799x. called ad799x.
config ASPEED_ADC
tristate "Aspeed ADC"
depends on ARCH_ASPEED || COMPILE_TEST
depends on COMMON_CLK
help
If you say yes here you get support for the ADC included in Aspeed
BMC SoCs.
To compile this driver as a module, choose M here: the module will be
called aspeed_adc.
config AT91_ADC config AT91_ADC
tristate "Atmel AT91 ADC" tristate "Atmel AT91 ADC"
depends on ARCH_AT91 depends on ARCH_AT91
...@@ -195,6 +206,17 @@ config CC10001_ADC ...@@ -195,6 +206,17 @@ config CC10001_ADC
This driver can also be built as a module. If so, the module will be This driver can also be built as a module. If so, the module will be
called cc10001_adc. called cc10001_adc.
config CPCAP_ADC
tristate "Motorola CPCAP PMIC ADC driver"
depends on MFD_CPCAP
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for Motorola CPCAP PMIC ADC.
This driver can also be built as a module. If so, the module will be
called cpcap-adc.
config DA9150_GPADC config DA9150_GPADC
tristate "Dialog DA9150 GPADC driver support" tristate "Dialog DA9150 GPADC driver support"
depends on MFD_DA9150 depends on MFD_DA9150
...@@ -326,6 +348,16 @@ config LTC2485 ...@@ -326,6 +348,16 @@ config LTC2485
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called ltc2485. called ltc2485.
config LTC2497
tristate "Linear Technology LTC2497 ADC driver"
depends on I2C
help
Say yes here to build support for Linear Technology LTC2497
16-Bit 8-/16-Channel Delta Sigma ADC.
To compile this driver as a module, choose M here: the module will be
called ltc2497.
config MAX1027 config MAX1027
tristate "Maxim max1027 ADC driver" tristate "Maxim max1027 ADC driver"
depends on SPI depends on SPI
...@@ -563,6 +595,7 @@ config SUN4I_GPADC ...@@ -563,6 +595,7 @@ config SUN4I_GPADC
tristate "Support for the Allwinner SoCs GPADC" tristate "Support for the Allwinner SoCs GPADC"
depends on IIO depends on IIO
depends on MFD_SUN4I_GPADC depends on MFD_SUN4I_GPADC
depends on THERMAL || !THERMAL_OF
help help
Say yes here to build support for Allwinner (A10, A13 and A31) SoCs Say yes here to build support for Allwinner (A10, A13 and A31) SoCs
GPADC. This ADC provides 4 channels which can be used as an ADC or as GPADC. This ADC provides 4 channels which can be used as an ADC or as
......
...@@ -14,12 +14,14 @@ obj-$(CONFIG_AD7791) += ad7791.o ...@@ -14,12 +14,14 @@ obj-$(CONFIG_AD7791) += ad7791.o
obj-$(CONFIG_AD7793) += ad7793.o obj-$(CONFIG_AD7793) += ad7793.o
obj-$(CONFIG_AD7887) += ad7887.o obj-$(CONFIG_AD7887) += ad7887.o
obj-$(CONFIG_AD799X) += ad799x.o obj-$(CONFIG_AD799X) += ad799x.o
obj-$(CONFIG_ASPEED_ADC) += aspeed_adc.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o
obj-$(CONFIG_AXP288_ADC) += axp288_adc.o obj-$(CONFIG_AXP288_ADC) += axp288_adc.o
obj-$(CONFIG_BCM_IPROC_ADC) += bcm_iproc_adc.o obj-$(CONFIG_BCM_IPROC_ADC) += bcm_iproc_adc.o
obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o
obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o
obj-$(CONFIG_CPCAP_ADC) += cpcap-adc.o
obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o
obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
...@@ -32,6 +34,7 @@ obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o ...@@ -32,6 +34,7 @@ obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
obj-$(CONFIG_LTC2485) += ltc2485.o obj-$(CONFIG_LTC2485) += ltc2485.o
obj-$(CONFIG_LTC2497) += ltc2497.o
obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1027) += max1027.o
obj-$(CONFIG_MAX11100) += max11100.o obj-$(CONFIG_MAX11100) += max11100.o
obj-$(CONFIG_MAX1363) += max1363.o obj-$(CONFIG_MAX1363) += max1363.o
......
...@@ -520,7 +520,7 @@ static struct attribute *ad799x_event_attributes[] = { ...@@ -520,7 +520,7 @@ static struct attribute *ad799x_event_attributes[] = {
NULL, NULL,
}; };
static struct attribute_group ad799x_event_attrs_group = { static const struct attribute_group ad799x_event_attrs_group = {
.attrs = ad799x_event_attributes, .attrs = ad799x_event_attributes,
}; };
......
/*
* Aspeed AST2400/2500 ADC
*
* Copyright (C) 2017 Google, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/iio/iio.h>
#include <linux/iio/driver.h>
#define ASPEED_RESOLUTION_BITS 10
#define ASPEED_CLOCKS_PER_SAMPLE 12
#define ASPEED_REG_ENGINE_CONTROL 0x00
#define ASPEED_REG_INTERRUPT_CONTROL 0x04
#define ASPEED_REG_VGA_DETECT_CONTROL 0x08
#define ASPEED_REG_CLOCK_CONTROL 0x0C
#define ASPEED_REG_MAX 0xC0
#define ASPEED_OPERATION_MODE_POWER_DOWN (0x0 << 1)
#define ASPEED_OPERATION_MODE_STANDBY (0x1 << 1)
#define ASPEED_OPERATION_MODE_NORMAL (0x7 << 1)
#define ASPEED_ENGINE_ENABLE BIT(0)
struct aspeed_adc_model_data {
const char *model_name;
unsigned int min_sampling_rate; // Hz
unsigned int max_sampling_rate; // Hz
unsigned int vref_voltage; // mV
};
struct aspeed_adc_data {
struct device *dev;
void __iomem *base;
spinlock_t clk_lock;
struct clk_hw *clk_prescaler;
struct clk_hw *clk_scaler;
};
#define ASPEED_CHAN(_idx, _data_reg_addr) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (_idx), \
.address = (_data_reg_addr), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
}
static const struct iio_chan_spec aspeed_adc_iio_channels[] = {
ASPEED_CHAN(0, 0x10),
ASPEED_CHAN(1, 0x12),
ASPEED_CHAN(2, 0x14),
ASPEED_CHAN(3, 0x16),
ASPEED_CHAN(4, 0x18),
ASPEED_CHAN(5, 0x1A),
ASPEED_CHAN(6, 0x1C),
ASPEED_CHAN(7, 0x1E),
ASPEED_CHAN(8, 0x20),
ASPEED_CHAN(9, 0x22),
ASPEED_CHAN(10, 0x24),
ASPEED_CHAN(11, 0x26),
ASPEED_CHAN(12, 0x28),
ASPEED_CHAN(13, 0x2A),
ASPEED_CHAN(14, 0x2C),
ASPEED_CHAN(15, 0x2E),
};
static int aspeed_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct aspeed_adc_data *data = iio_priv(indio_dev);
const struct aspeed_adc_model_data *model_data =
of_device_get_match_data(data->dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
*val = readw(data->base + chan->address);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = model_data->vref_voltage;
*val2 = ASPEED_RESOLUTION_BITS;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_SAMP_FREQ:
*val = clk_get_rate(data->clk_scaler->clk) /
ASPEED_CLOCKS_PER_SAMPLE;
return IIO_VAL_INT;
default:
return -EINVAL;
}
}
static int aspeed_adc_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct aspeed_adc_data *data = iio_priv(indio_dev);
const struct aspeed_adc_model_data *model_data =
of_device_get_match_data(data->dev);
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
if (val < model_data->min_sampling_rate ||
val > model_data->max_sampling_rate)
return -EINVAL;
clk_set_rate(data->clk_scaler->clk,
val * ASPEED_CLOCKS_PER_SAMPLE);
return 0;
case IIO_CHAN_INFO_SCALE:
case IIO_CHAN_INFO_RAW:
/*
* Technically, these could be written but the only reasons
* for doing so seem better handled in userspace. EPERM is
* returned to signal this is a policy choice rather than a
* hardware limitation.
*/
return -EPERM;
default:
return -EINVAL;
}
}
static int aspeed_adc_reg_access(struct iio_dev *indio_dev,
unsigned int reg, unsigned int writeval,
unsigned int *readval)
{
struct aspeed_adc_data *data = iio_priv(indio_dev);
if (!readval || reg % 4 || reg > ASPEED_REG_MAX)
return -EINVAL;
*readval = readl(data->base + reg);
return 0;
}
static const struct iio_info aspeed_adc_iio_info = {
.driver_module = THIS_MODULE,
.read_raw = aspeed_adc_read_raw,
.write_raw = aspeed_adc_write_raw,
.debugfs_reg_access = aspeed_adc_reg_access,
};
static int aspeed_adc_probe(struct platform_device *pdev)
{
struct iio_dev *indio_dev;
struct aspeed_adc_data *data;
const struct aspeed_adc_model_data *model_data;
struct resource *res;
const char *clk_parent_name;
int ret;
u32 adc_engine_control_reg_val;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
data->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(data->base))
return PTR_ERR(data->base);
/* Register ADC clock prescaler with source specified by device tree. */
spin_lock_init(&data->clk_lock);
clk_parent_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
data->clk_prescaler = clk_hw_register_divider(
&pdev->dev, "prescaler", clk_parent_name, 0,
data->base + ASPEED_REG_CLOCK_CONTROL,
17, 15, 0, &data->clk_lock);
if (IS_ERR(data->clk_prescaler))
return PTR_ERR(data->clk_prescaler);
/*
* Register ADC clock scaler downstream from the prescaler. Allow rate
* setting to adjust the prescaler as well.
*/
data->clk_scaler = clk_hw_register_divider(
&pdev->dev, "scaler", "prescaler",
CLK_SET_RATE_PARENT,
data->base + ASPEED_REG_CLOCK_CONTROL,
0, 10, 0, &data->clk_lock);
if (IS_ERR(data->clk_scaler)) {
ret = PTR_ERR(data->clk_scaler);
goto scaler_error;
}
/* Start all channels in normal mode. */
clk_prepare_enable(data->clk_scaler->clk);
adc_engine_control_reg_val = GENMASK(31, 16) |
ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE;
writel(adc_engine_control_reg_val,
data->base + ASPEED_REG_ENGINE_CONTROL);
model_data = of_device_get_match_data(&pdev->dev);
indio_dev->name = model_data->model_name;
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &aspeed_adc_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = aspeed_adc_iio_channels;
indio_dev->num_channels = ARRAY_SIZE(aspeed_adc_iio_channels);
ret = iio_device_register(indio_dev);
if (ret)
goto iio_register_error;
return 0;
iio_register_error:
writel(ASPEED_OPERATION_MODE_POWER_DOWN,
data->base + ASPEED_REG_ENGINE_CONTROL);
clk_disable_unprepare(data->clk_scaler->clk);
clk_hw_unregister_divider(data->clk_scaler);
scaler_error:
clk_hw_unregister_divider(data->clk_prescaler);
return ret;
}
static int aspeed_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct aspeed_adc_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
writel(ASPEED_OPERATION_MODE_POWER_DOWN,
data->base + ASPEED_REG_ENGINE_CONTROL);
clk_disable_unprepare(data->clk_scaler->clk);
clk_hw_unregister_divider(data->clk_scaler);
clk_hw_unregister_divider(data->clk_prescaler);
return 0;
}
static const struct aspeed_adc_model_data ast2400_model_data = {
.model_name = "ast2400-adc",
.vref_voltage = 2500, // mV
.min_sampling_rate = 10000,
.max_sampling_rate = 500000,
};
static const struct aspeed_adc_model_data ast2500_model_data = {
.model_name = "ast2500-adc",
.vref_voltage = 1800, // mV
.min_sampling_rate = 1,
.max_sampling_rate = 1000000,
};
static const struct of_device_id aspeed_adc_matches[] = {
{ .compatible = "aspeed,ast2400-adc", .data = &ast2400_model_data },
{ .compatible = "aspeed,ast2500-adc", .data = &ast2500_model_data },
{},
};
MODULE_DEVICE_TABLE(of, aspeed_adc_matches);
static struct platform_driver aspeed_adc_driver = {
.probe = aspeed_adc_probe,
.remove = aspeed_adc_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = aspeed_adc_matches,
}
};
module_platform_driver(aspeed_adc_driver);
MODULE_AUTHOR("Rick Altherr <raltherr@google.com>");
MODULE_DESCRIPTION("Aspeed AST2400/2500 ADC Driver");
MODULE_LICENSE("GPL");
This diff is collapsed.
...@@ -579,7 +579,7 @@ static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev, int *x, int *y) ...@@ -579,7 +579,7 @@ static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev, int *x, int *y)
static irqreturn_t exynos_adc_isr(int irq, void *dev_id) static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
{ {
struct exynos_adc *info = (struct exynos_adc *)dev_id; struct exynos_adc *info = dev_id;
u32 mask = info->data->mask; u32 mask = info->data->mask;
/* Read value */ /* Read value */
......
...@@ -369,7 +369,7 @@ static struct attribute *hx711_attributes[] = { ...@@ -369,7 +369,7 @@ static struct attribute *hx711_attributes[] = {
NULL, NULL,
}; };
static struct attribute_group hx711_attribute_group = { static const struct attribute_group hx711_attribute_group = {
.attrs = hx711_attributes, .attrs = hx711_attributes,
}; };
......
...@@ -365,7 +365,7 @@ static int imx7d_adc_read_data(struct imx7d_adc *info) ...@@ -365,7 +365,7 @@ static int imx7d_adc_read_data(struct imx7d_adc *info)
static irqreturn_t imx7d_adc_isr(int irq, void *dev_id) static irqreturn_t imx7d_adc_isr(int irq, void *dev_id)
{ {
struct imx7d_adc *info = (struct imx7d_adc *)dev_id; struct imx7d_adc *info = dev_id;
int status; int status;
status = readl(info->regs + IMX7D_REG_ADC_INT_STATUS); status = readl(info->regs + IMX7D_REG_ADC_INT_STATUS);
......
/*
* ltc2497.c - Driver for Analog Devices/Linear Technology LTC2497 ADC
*
* Copyright (C) 2017 Analog Devices Inc.
*
* Licensed under the GPL-2.
*
* Datasheet: http://cds.linear.com/docs/en/datasheet/2497fd.pdf
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regulator/consumer.h>
#define LTC2497_ENABLE 0xA0
#define LTC2497_SGL BIT(4)
#define LTC2497_DIFF 0
#define LTC2497_SIGN BIT(3)
#define LTC2497_CONFIG_DEFAULT LTC2497_ENABLE
#define LTC2497_CONVERSION_TIME_MS 150ULL
struct ltc2497_st {
struct i2c_client *client;
struct regulator *ref;
ktime_t time_prev;
u8 addr_prev;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
__be32 buf ____cacheline_aligned;
};
static int ltc2497_wait_conv(struct ltc2497_st *st)
{
s64 time_elapsed;
time_elapsed = ktime_ms_delta(ktime_get(), st->time_prev);
if (time_elapsed < LTC2497_CONVERSION_TIME_MS) {
/* delay if conversion time not passed
* since last read or write
*/
if (msleep_interruptible(
LTC2497_CONVERSION_TIME_MS - time_elapsed))
return -ERESTARTSYS;
return 0;
}
if (time_elapsed - LTC2497_CONVERSION_TIME_MS <= 0) {
/* We're in automatic mode -
* so the last reading is stil not outdated
*/
return 0;
}
return 1;
}
static int ltc2497_read(struct ltc2497_st *st, u8 address, int *val)
{
struct i2c_client *client = st->client;
int ret;
ret = ltc2497_wait_conv(st);
if (ret < 0)
return ret;
if (ret || st->addr_prev != address) {
ret = i2c_smbus_write_byte(st->client,
LTC2497_ENABLE | address);
if (ret < 0)
return ret;
st->addr_prev = address;
if (msleep_interruptible(LTC2497_CONVERSION_TIME_MS))
return -ERESTARTSYS;
}
ret = i2c_master_recv(client, (char *)&st->buf, 3);
if (ret < 0) {
dev_err(&client->dev, "i2c_master_recv failed\n");
return ret;
}
st->time_prev = ktime_get();
/* convert and shift the result,
* and finally convert from offset binary to signed integer
*/
*val = (be32_to_cpu(st->buf) >> 14) - (1 << 17);
return ret;
}
static int ltc2497_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct ltc2497_st *st = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
ret = ltc2497_read(st, chan->address, val);
mutex_unlock(&indio_dev->mlock);
if (ret < 0)
return ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
ret = regulator_get_voltage(st->ref);
if (ret < 0)
return ret;
*val = ret / 1000;
*val2 = 17;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
}
#define LTC2497_CHAN(_chan, _addr) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (_chan), \
.address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
#define LTC2497_CHAN_DIFF(_chan, _addr) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 1 : 0), \
.channel2 = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 0 : 1),\
.address = (_addr | _chan), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.differential = 1, \
}
static const struct iio_chan_spec ltc2497_channel[] = {
LTC2497_CHAN(0, LTC2497_SGL),
LTC2497_CHAN(1, LTC2497_SGL),
LTC2497_CHAN(2, LTC2497_SGL),
LTC2497_CHAN(3, LTC2497_SGL),
LTC2497_CHAN(4, LTC2497_SGL),
LTC2497_CHAN(5, LTC2497_SGL),
LTC2497_CHAN(6, LTC2497_SGL),
LTC2497_CHAN(7, LTC2497_SGL),
LTC2497_CHAN(8, LTC2497_SGL),
LTC2497_CHAN(9, LTC2497_SGL),
LTC2497_CHAN(10, LTC2497_SGL),
LTC2497_CHAN(11, LTC2497_SGL),
LTC2497_CHAN(12, LTC2497_SGL),
LTC2497_CHAN(13, LTC2497_SGL),
LTC2497_CHAN(14, LTC2497_SGL),
LTC2497_CHAN(15, LTC2497_SGL),
LTC2497_CHAN_DIFF(0, LTC2497_DIFF),
LTC2497_CHAN_DIFF(1, LTC2497_DIFF),
LTC2497_CHAN_DIFF(2, LTC2497_DIFF),
LTC2497_CHAN_DIFF(3, LTC2497_DIFF),
LTC2497_CHAN_DIFF(4, LTC2497_DIFF),
LTC2497_CHAN_DIFF(5, LTC2497_DIFF),
LTC2497_CHAN_DIFF(6, LTC2497_DIFF),
LTC2497_CHAN_DIFF(7, LTC2497_DIFF),
LTC2497_CHAN_DIFF(0, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(1, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(2, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(3, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(4, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(5, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(6, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(7, LTC2497_DIFF | LTC2497_SIGN),
};
static const struct iio_info ltc2497_info = {
.read_raw = ltc2497_read_raw,
.driver_module = THIS_MODULE,
};
static int ltc2497_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct iio_dev *indio_dev;
struct ltc2497_st *st;
int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
I2C_FUNC_SMBUS_WRITE_BYTE))
return -EOPNOTSUPP;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
st->client = client;
indio_dev->dev.parent = &client->dev;
indio_dev->name = id->name;
indio_dev->info = &ltc2497_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = ltc2497_channel;
indio_dev->num_channels = ARRAY_SIZE(ltc2497_channel);
st->ref = devm_regulator_get(&client->dev, "vref");
if (IS_ERR(st->ref))
return PTR_ERR(st->ref);
ret = regulator_enable(st->ref);
if (ret < 0)
return ret;
ret = i2c_smbus_write_byte(st->client, LTC2497_CONFIG_DEFAULT);
if (ret < 0)
goto err_regulator_disable;
st->addr_prev = LTC2497_CONFIG_DEFAULT;
st->time_prev = ktime_get();
ret = iio_device_register(indio_dev);
if (ret < 0)
goto err_regulator_disable;
return 0;
err_regulator_disable:
regulator_disable(st->ref);
return ret;
}
static int ltc2497_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct ltc2497_st *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
regulator_disable(st->ref);
return 0;
}
static const struct i2c_device_id ltc2497_id[] = {
{ "ltc2497", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ltc2497_id);
static const struct of_device_id ltc2497_of_match[] = {
{ .compatible = "lltc,ltc2497", },
{},
};
MODULE_DEVICE_TABLE(of, ltc2497_of_match);
static struct i2c_driver ltc2497_driver = {
.driver = {
.name = "ltc2497",
.of_match_table = of_match_ptr(ltc2497_of_match),
},
.probe = ltc2497_probe,
.remove = ltc2497_remove,
.id_table = ltc2497_id,
};
module_i2c_driver(ltc2497_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Linear Technology LTC2497 ADC driver");
MODULE_LICENSE("GPL v2");
...@@ -364,7 +364,7 @@ static int max1027_set_trigger_state(struct iio_trigger *trig, bool state) ...@@ -364,7 +364,7 @@ static int max1027_set_trigger_state(struct iio_trigger *trig, bool state)
static irqreturn_t max1027_trigger_handler(int irq, void *private) static irqreturn_t max1027_trigger_handler(int irq, void *private)
{ {
struct iio_poll_func *pf = (struct iio_poll_func *)private; struct iio_poll_func *pf = private;
struct iio_dev *indio_dev = pf->indio_dev; struct iio_dev *indio_dev = pf->indio_dev;
struct max1027_state *st = iio_priv(indio_dev); struct max1027_state *st = iio_priv(indio_dev);
......
...@@ -124,8 +124,8 @@ static int max11100_probe(struct spi_device *spi) ...@@ -124,8 +124,8 @@ static int max11100_probe(struct spi_device *spi)
indio_dev->name = "max11100"; indio_dev->name = "max11100";
indio_dev->info = &max11100_info; indio_dev->info = &max11100_info;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = max11100_channels, indio_dev->channels = max11100_channels;
indio_dev->num_channels = ARRAY_SIZE(max11100_channels), indio_dev->num_channels = ARRAY_SIZE(max11100_channels);
state->vref_reg = devm_regulator_get(&spi->dev, "vref"); state->vref_reg = devm_regulator_get(&spi->dev, "vref");
if (IS_ERR(state->vref_reg)) if (IS_ERR(state->vref_reg))
......
...@@ -1007,7 +1007,7 @@ static struct attribute *max1363_event_attributes[] = { ...@@ -1007,7 +1007,7 @@ static struct attribute *max1363_event_attributes[] = {
NULL, NULL,
}; };
static struct attribute_group max1363_event_attribute_group = { static const struct attribute_group max1363_event_attribute_group = {
.attrs = max1363_event_attributes, .attrs = max1363_event_attributes,
}; };
......
...@@ -166,6 +166,8 @@ ...@@ -166,6 +166,8 @@
#define MESON_SAR_ADC_MAX_FIFO_SIZE 32 #define MESON_SAR_ADC_MAX_FIFO_SIZE 32
#define MESON_SAR_ADC_TIMEOUT 100 /* ms */ #define MESON_SAR_ADC_TIMEOUT 100 /* ms */
/* for use with IIO_VAL_INT_PLUS_MICRO */
#define MILLION 1000000
#define MESON_SAR_ADC_CHAN(_chan) { \ #define MESON_SAR_ADC_CHAN(_chan) { \
.type = IIO_VOLTAGE, \ .type = IIO_VOLTAGE, \
...@@ -173,7 +175,9 @@ ...@@ -173,7 +175,9 @@
.channel = _chan, \ .channel = _chan, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ BIT(IIO_CHAN_INFO_AVERAGE_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_CALIBBIAS) | \
BIT(IIO_CHAN_INFO_CALIBSCALE), \
.datasheet_name = "SAR_ADC_CH"#_chan, \ .datasheet_name = "SAR_ADC_CH"#_chan, \
} }
...@@ -233,6 +237,8 @@ struct meson_sar_adc_priv { ...@@ -233,6 +237,8 @@ struct meson_sar_adc_priv {
struct clk *adc_div_clk; struct clk *adc_div_clk;
struct clk_divider clk_div; struct clk_divider clk_div;
struct completion done; struct completion done;
int calibbias;
int calibscale;
}; };
static const struct regmap_config meson_sar_adc_regmap_config = { static const struct regmap_config meson_sar_adc_regmap_config = {
...@@ -252,6 +258,17 @@ static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev) ...@@ -252,6 +258,17 @@ static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev)
return FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval); return FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
} }
static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
int tmp;
/* use val_calib = scale * val_raw + offset calibration function */
tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias;
return clamp(tmp, 0, (1 << priv->data->resolution) - 1);
}
static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev) static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev)
{ {
struct meson_sar_adc_priv *priv = iio_priv(indio_dev); struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
...@@ -302,7 +319,7 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev, ...@@ -302,7 +319,7 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval); fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval);
fifo_val &= GENMASK(priv->data->resolution - 1, 0); fifo_val &= GENMASK(priv->data->resolution - 1, 0);
*val = fifo_val; *val = meson_sar_adc_calib_val(indio_dev, fifo_val);
return 0; return 0;
} }
...@@ -527,6 +544,15 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev, ...@@ -527,6 +544,15 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev,
*val2 = priv->data->resolution; *val2 = priv->data->resolution;
return IIO_VAL_FRACTIONAL_LOG2; return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_CALIBBIAS:
*val = priv->calibbias;
return IIO_VAL_INT;
case IIO_CHAN_INFO_CALIBSCALE:
*val = priv->calibscale / MILLION;
*val2 = priv->calibscale % MILLION;
return IIO_VAL_INT_PLUS_MICRO;
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -762,6 +788,47 @@ static irqreturn_t meson_sar_adc_irq(int irq, void *data) ...@@ -762,6 +788,47 @@ static irqreturn_t meson_sar_adc_irq(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int meson_sar_adc_calib(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
int ret, nominal0, nominal1, value0, value1;
/* use points 25% and 75% for calibration */
nominal0 = (1 << priv->data->resolution) / 4;
nominal1 = (1 << priv->data->resolution) * 3 / 4;
meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4);
usleep_range(10, 20);
ret = meson_sar_adc_get_sample(indio_dev,
&meson_sar_adc_iio_channels[7],
MEAN_AVERAGING, EIGHT_SAMPLES, &value0);
if (ret < 0)
goto out;
meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4);
usleep_range(10, 20);
ret = meson_sar_adc_get_sample(indio_dev,
&meson_sar_adc_iio_channels[7],
MEAN_AVERAGING, EIGHT_SAMPLES, &value1);
if (ret < 0)
goto out;
if (value1 <= value0) {
ret = -EINVAL;
goto out;
}
priv->calibscale = div_s64((nominal1 - nominal0) * (s64)MILLION,
value1 - value0);
priv->calibbias = nominal0 - div_s64((s64)value0 * priv->calibscale,
MILLION);
ret = 0;
out:
meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT);
return ret;
}
static const struct iio_info meson_sar_adc_iio_info = { static const struct iio_info meson_sar_adc_iio_info = {
.read_raw = meson_sar_adc_iio_info_read_raw, .read_raw = meson_sar_adc_iio_info_read_raw,
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
...@@ -901,6 +968,8 @@ static int meson_sar_adc_probe(struct platform_device *pdev) ...@@ -901,6 +968,8 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
return PTR_ERR(priv->vref); return PTR_ERR(priv->vref);
} }
priv->calibscale = MILLION;
ret = meson_sar_adc_init(indio_dev); ret = meson_sar_adc_init(indio_dev);
if (ret) if (ret)
goto err; goto err;
...@@ -909,6 +978,10 @@ static int meson_sar_adc_probe(struct platform_device *pdev) ...@@ -909,6 +978,10 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
if (ret) if (ret)
goto err; goto err;
ret = meson_sar_adc_calib(indio_dev);
if (ret)
dev_warn(&pdev->dev, "calibration failed\n");
platform_set_drvdata(pdev, indio_dev); platform_set_drvdata(pdev, indio_dev);
ret = iio_device_register(indio_dev); ret = iio_device_register(indio_dev);
......
...@@ -109,7 +109,7 @@ static int rockchip_saradc_read_raw(struct iio_dev *indio_dev, ...@@ -109,7 +109,7 @@ static int rockchip_saradc_read_raw(struct iio_dev *indio_dev,
static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id) static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id)
{ {
struct rockchip_saradc *info = (struct rockchip_saradc *)dev_id; struct rockchip_saradc *info = dev_id;
/* Read value */ /* Read value */
info->last_val = readl_relaxed(info->regs + SARADC_DATA); info->last_val = readl_relaxed(info->regs + SARADC_DATA);
......
...@@ -382,7 +382,7 @@ static int sun4i_gpadc_runtime_resume(struct device *dev) ...@@ -382,7 +382,7 @@ static int sun4i_gpadc_runtime_resume(struct device *dev)
static int sun4i_gpadc_get_temp(void *data, int *temp) static int sun4i_gpadc_get_temp(void *data, int *temp)
{ {
struct sun4i_gpadc_iio *info = (struct sun4i_gpadc_iio *)data; struct sun4i_gpadc_iio *info = data;
int val, scale, offset; int val, scale, offset;
if (sun4i_gpadc_temp_read(info->indio_dev, &val)) if (sun4i_gpadc_temp_read(info->indio_dev, &val))
......
...@@ -584,7 +584,7 @@ static int vf610_adc_read_data(struct vf610_adc *info) ...@@ -584,7 +584,7 @@ static int vf610_adc_read_data(struct vf610_adc *info)
static irqreturn_t vf610_adc_isr(int irq, void *dev_id) static irqreturn_t vf610_adc_isr(int irq, void *dev_id)
{ {
struct iio_dev *indio_dev = (struct iio_dev *)dev_id; struct iio_dev *indio_dev = dev_id;
struct vf610_adc *info = iio_priv(indio_dev); struct vf610_adc *info = iio_priv(indio_dev);
int coco; int coco;
......
...@@ -163,7 +163,7 @@ static int ams_iaqcore_probe(struct i2c_client *client, ...@@ -163,7 +163,7 @@ static int ams_iaqcore_probe(struct i2c_client *client,
mutex_init(&data->lock); mutex_init(&data->lock);
indio_dev->dev.parent = &client->dev; indio_dev->dev.parent = &client->dev;
indio_dev->info = &ams_iaqcore_info, indio_dev->info = &ams_iaqcore_info;
indio_dev->name = dev_name(&client->dev); indio_dev->name = dev_name(&client->dev);
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
......
...@@ -393,7 +393,7 @@ static int vz89x_probe(struct i2c_client *client, ...@@ -393,7 +393,7 @@ static int vz89x_probe(struct i2c_client *client,
mutex_init(&data->lock); mutex_init(&data->lock);
indio_dev->dev.parent = &client->dev; indio_dev->dev.parent = &client->dev;
indio_dev->info = &vz89x_info, indio_dev->info = &vz89x_info;
indio_dev->name = dev_name(&client->dev); indio_dev->name = dev_name(&client->dev);
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
......
...@@ -267,31 +267,12 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) ...@@ -267,31 +267,12 @@ static int cros_ec_sensors_probe(struct platform_device *pdev)
else else
state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd; state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
ret = iio_triggered_buffer_setup(indio_dev, NULL, ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
cros_ec_sensors_capture, NULL); cros_ec_sensors_capture, NULL);
if (ret) if (ret)
return ret; return ret;
ret = iio_device_register(indio_dev); return devm_iio_device_register(dev, indio_dev);
if (ret)
goto error_uninit_buffer;
return 0;
error_uninit_buffer:
iio_triggered_buffer_cleanup(indio_dev);
return ret;
}
static int cros_ec_sensors_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
return 0;
} }
static const struct platform_device_id cros_ec_sensors_ids[] = { static const struct platform_device_id cros_ec_sensors_ids[] = {
...@@ -313,7 +294,6 @@ static struct platform_driver cros_ec_sensors_platform_driver = { ...@@ -313,7 +294,6 @@ static struct platform_driver cros_ec_sensors_platform_driver = {
.name = "cros-ec-sensors", .name = "cros-ec-sensors",
}, },
.probe = cros_ec_sensors_probe, .probe = cros_ec_sensors_probe,
.remove = cros_ec_sensors_remove,
.id_table = cros_ec_sensors_ids, .id_table = cros_ec_sensors_ids,
}; };
module_platform_driver(cros_ec_sensors_platform_driver); module_platform_driver(cros_ec_sensors_platform_driver);
......
...@@ -38,6 +38,12 @@ static struct { ...@@ -38,6 +38,12 @@ static struct {
{HID_USAGE_SENSOR_ACCEL_3D, {HID_USAGE_SENSOR_ACCEL_3D,
HID_USAGE_SENSOR_UNITS_G, 9, 806650000}, HID_USAGE_SENSOR_UNITS_G, 9, 806650000},
{HID_USAGE_SENSOR_GRAVITY_VECTOR, 0, 9, 806650000},
{HID_USAGE_SENSOR_GRAVITY_VECTOR,
HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0},
{HID_USAGE_SENSOR_GRAVITY_VECTOR,
HID_USAGE_SENSOR_UNITS_G, 9, 806650000},
{HID_USAGE_SENSOR_GYRO_3D, 0, 0, 17453293}, {HID_USAGE_SENSOR_GYRO_3D, 0, 0, 17453293},
{HID_USAGE_SENSOR_GYRO_3D, {HID_USAGE_SENSOR_GYRO_3D,
HID_USAGE_SENSOR_UNITS_RADIANS_PER_SECOND, 1, 0}, HID_USAGE_SENSOR_UNITS_RADIANS_PER_SECOND, 1, 0},
...@@ -65,6 +71,8 @@ static struct { ...@@ -65,6 +71,8 @@ static struct {
{HID_USAGE_SENSOR_TEMPERATURE, 0, 1000, 0}, {HID_USAGE_SENSOR_TEMPERATURE, 0, 1000, 0},
{HID_USAGE_SENSOR_TEMPERATURE, HID_USAGE_SENSOR_UNITS_DEGREES, 1000, 0}, {HID_USAGE_SENSOR_TEMPERATURE, HID_USAGE_SENSOR_UNITS_DEGREES, 1000, 0},
{HID_USAGE_SENSOR_HUMIDITY, 0, 1000, 0},
}; };
static int pow_10(unsigned power) static int pow_10(unsigned power)
......
...@@ -74,7 +74,7 @@ EXPORT_SYMBOL(ms_sensors_reset); ...@@ -74,7 +74,7 @@ EXPORT_SYMBOL(ms_sensors_reset);
int ms_sensors_read_prom_word(void *cli, int cmd, u16 *word) int ms_sensors_read_prom_word(void *cli, int cmd, u16 *word)
{ {
int ret; int ret;
struct i2c_client *client = (struct i2c_client *)cli; struct i2c_client *client = cli;
ret = i2c_smbus_read_word_swapped(client, cmd); ret = i2c_smbus_read_word_swapped(client, cmd);
if (ret < 0) { if (ret < 0) {
...@@ -107,7 +107,7 @@ int ms_sensors_convert_and_read(void *cli, u8 conv, u8 rd, ...@@ -107,7 +107,7 @@ int ms_sensors_convert_and_read(void *cli, u8 conv, u8 rd,
{ {
int ret; int ret;
__be32 buf = 0; __be32 buf = 0;
struct i2c_client *client = (struct i2c_client *)cli; struct i2c_client *client = cli;
/* Trigger conversion */ /* Trigger conversion */
ret = i2c_smbus_write_byte(client, conv); ret = i2c_smbus_write_byte(client, conv);
......
...@@ -212,7 +212,7 @@ static struct attribute *ad5504_ev_attributes[] = { ...@@ -212,7 +212,7 @@ static struct attribute *ad5504_ev_attributes[] = {
NULL, NULL,
}; };
static struct attribute_group ad5504_ev_attribute_group = { static const struct attribute_group ad5504_ev_attribute_group = {
.attrs = ad5504_ev_attributes, .attrs = ad5504_ev_attributes,
}; };
...@@ -223,7 +223,7 @@ static irqreturn_t ad5504_event_handler(int irq, void *private) ...@@ -223,7 +223,7 @@ static irqreturn_t ad5504_event_handler(int irq, void *private)
0, 0,
IIO_EV_TYPE_THRESH, IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING), IIO_EV_DIR_RISING),
iio_get_time_ns((struct iio_dev *)private)); iio_get_time_ns(private));
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -36,6 +36,20 @@ config HDC100X ...@@ -36,6 +36,20 @@ config HDC100X
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called hdc100x. will be called hdc100x.
config HID_SENSOR_HUMIDITY
tristate "HID Environmental humidity sensor"
depends on HID_SENSOR_HUB
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select HID_SENSOR_IIO_COMMON
select HID_SENSOR_IIO_TRIGGER
help
Say yes here to build support for the HID SENSOR
humidity driver
To compile this driver as a module, choose M here: the module
will be called hid-sensor-humidity.
config HTS221 config HTS221
tristate "STMicroelectronics HTS221 sensor Driver" tristate "STMicroelectronics HTS221 sensor Driver"
depends on (I2C || SPI) depends on (I2C || SPI)
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
obj-$(CONFIG_AM2315) += am2315.o obj-$(CONFIG_AM2315) += am2315.o
obj-$(CONFIG_DHT11) += dht11.o obj-$(CONFIG_DHT11) += dht11.o
obj-$(CONFIG_HDC100X) += hdc100x.o obj-$(CONFIG_HDC100X) += hdc100x.o
obj-$(CONFIG_HID_SENSOR_HUMIDITY) += hid-sensor-humidity.o
hts221-y := hts221_core.o \ hts221-y := hts221_core.o \
hts221_buffer.o hts221_buffer.o
...@@ -15,3 +16,5 @@ obj-$(CONFIG_HTS221_SPI) += hts221_spi.o ...@@ -15,3 +16,5 @@ obj-$(CONFIG_HTS221_SPI) += hts221_spi.o
obj-$(CONFIG_HTU21) += htu21.o obj-$(CONFIG_HTU21) += htu21.o
obj-$(CONFIG_SI7005) += si7005.o obj-$(CONFIG_SI7005) += si7005.o
obj-$(CONFIG_SI7020) += si7020.o obj-$(CONFIG_SI7020) += si7020.o
ccflags-y += -I$(srctree)/drivers/iio/common/hid-sensors
...@@ -79,7 +79,7 @@ static struct attribute *hdc100x_attributes[] = { ...@@ -79,7 +79,7 @@ static struct attribute *hdc100x_attributes[] = {
NULL NULL
}; };
static struct attribute_group hdc100x_attribute_group = { static const struct attribute_group hdc100x_attribute_group = {
.attrs = hdc100x_attributes, .attrs = hdc100x_attributes,
}; };
......
/*
* HID Sensors Driver
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program.
*/
#include <linux/device.h>
#include <linux/hid-sensor-hub.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "hid-sensor-trigger.h"
struct hid_humidity_state {
struct hid_sensor_common common_attributes;
struct hid_sensor_hub_attribute_info humidity_attr;
s32 humidity_data;
int scale_pre_decml;
int scale_post_decml;
int scale_precision;
int value_offset;
};
/* Channel definitions */
static const struct iio_chan_spec humidity_channels[] = {
{
.type = IIO_HUMIDITYRELATIVE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_HYSTERESIS),
},
IIO_CHAN_SOFT_TIMESTAMP(1)
};
/* Adjust channel real bits based on report descriptor */
static void humidity_adjust_channel_bit_mask(struct iio_chan_spec *channels,
int channel, int size)
{
channels[channel].scan_type.sign = 's';
/* Real storage bits will change based on the report desc. */
channels[channel].scan_type.realbits = size * 8;
/* Maximum size of a sample to capture is s32 */
channels[channel].scan_type.storagebits = sizeof(s32) * 8;
}
static int humidity_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct hid_humidity_state *humid_st = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (chan->type != IIO_HUMIDITYRELATIVE)
return -EINVAL;
hid_sensor_power_state(&humid_st->common_attributes, true);
*val = sensor_hub_input_attr_get_raw_value(
humid_st->common_attributes.hsdev,
HID_USAGE_SENSOR_HUMIDITY,
HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY,
humid_st->humidity_attr.report_id,
SENSOR_HUB_SYNC);
hid_sensor_power_state(&humid_st->common_attributes, false);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = humid_st->scale_pre_decml;
*val2 = humid_st->scale_post_decml;
return humid_st->scale_precision;
case IIO_CHAN_INFO_OFFSET:
*val = humid_st->value_offset;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SAMP_FREQ:
return hid_sensor_read_samp_freq_value(
&humid_st->common_attributes, val, val2);
case IIO_CHAN_INFO_HYSTERESIS:
return hid_sensor_read_raw_hyst_value(
&humid_st->common_attributes, val, val2);
default:
return -EINVAL;
}
}
static int humidity_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct hid_humidity_state *humid_st = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
return hid_sensor_write_samp_freq_value(
&humid_st->common_attributes, val, val2);
case IIO_CHAN_INFO_HYSTERESIS:
return hid_sensor_write_raw_hyst_value(
&humid_st->common_attributes, val, val2);
default:
return -EINVAL;
}
}
static const struct iio_info humidity_info = {
.driver_module = THIS_MODULE,
.read_raw = &humidity_read_raw,
.write_raw = &humidity_write_raw,
};
/* Callback handler to send event after all samples are received and captured */
static int humidity_proc_event(struct hid_sensor_hub_device *hsdev,
unsigned int usage_id, void *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct hid_humidity_state *humid_st = iio_priv(indio_dev);
if (atomic_read(&humid_st->common_attributes.data_ready))
iio_push_to_buffers_with_timestamp(indio_dev,
&humid_st->humidity_data,
iio_get_time_ns(indio_dev));
return 0;
}
/* Capture samples in local storage */
static int humidity_capture_sample(struct hid_sensor_hub_device *hsdev,
unsigned int usage_id, size_t raw_len,
char *raw_data, void *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct hid_humidity_state *humid_st = iio_priv(indio_dev);
switch (usage_id) {
case HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY:
humid_st->humidity_data = *(s32 *)raw_data;
return 0;
default:
return -EINVAL;
}
}
/* Parse report which is specific to an usage id */
static int humidity_parse_report(struct platform_device *pdev,
struct hid_sensor_hub_device *hsdev,
struct iio_chan_spec *channels,
unsigned int usage_id,
struct hid_humidity_state *st)
{
int ret;
ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT,
usage_id,
HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY,
&st->humidity_attr);
if (ret < 0)
return ret;
humidity_adjust_channel_bit_mask(channels, 0, st->humidity_attr.size);
st->scale_precision = hid_sensor_format_scale(
HID_USAGE_SENSOR_HUMIDITY,
&st->humidity_attr,
&st->scale_pre_decml,
&st->scale_post_decml);
/* Set Sensitivity field ids, when there is no individual modifier */
if (st->common_attributes.sensitivity.index < 0)
sensor_hub_input_get_attribute_info(hsdev,
HID_FEATURE_REPORT, usage_id,
HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS |
HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY,
&st->common_attributes.sensitivity);
return ret;
}
static struct hid_sensor_hub_callbacks humidity_callbacks = {
.send_event = &humidity_proc_event,
.capture_sample = &humidity_capture_sample,
};
/* Function to initialize the processing for usage id */
static int hid_humidity_probe(struct platform_device *pdev)
{
static const char *name = "humidity";
struct iio_dev *indio_dev;
struct hid_humidity_state *humid_st;
struct iio_chan_spec *humid_chans;
struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*humid_st));
if (!indio_dev)
return -ENOMEM;
humid_st = iio_priv(indio_dev);
humid_st->common_attributes.hsdev = hsdev;
humid_st->common_attributes.pdev = pdev;
ret = hid_sensor_parse_common_attributes(hsdev,
HID_USAGE_SENSOR_HUMIDITY,
&humid_st->common_attributes);
if (ret)
return ret;
humid_chans = devm_kmemdup(&indio_dev->dev, humidity_channels,
sizeof(humidity_channels), GFP_KERNEL);
if (!humid_chans)
return -ENOMEM;
ret = humidity_parse_report(pdev, hsdev, humid_chans,
HID_USAGE_SENSOR_HUMIDITY, humid_st);
if (ret)
return ret;
indio_dev->channels = humid_chans;
indio_dev->num_channels = ARRAY_SIZE(humidity_channels);
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &humidity_info;
indio_dev->name = name;
indio_dev->modes = INDIO_DIRECT_MODE;
ret = devm_iio_triggered_buffer_setup(&pdev->dev, indio_dev,
&iio_pollfunc_store_time, NULL, NULL);
if (ret)
return ret;
atomic_set(&humid_st->common_attributes.data_ready, 0);
ret = hid_sensor_setup_trigger(indio_dev, name,
&humid_st->common_attributes);
if (ret)
return ret;
platform_set_drvdata(pdev, indio_dev);
humidity_callbacks.pdev = pdev;
ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY,
&humidity_callbacks);
if (ret)
goto error_remove_trigger;
ret = iio_device_register(indio_dev);
if (ret)
goto error_remove_callback;
return ret;
error_remove_callback:
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY);
error_remove_trigger:
hid_sensor_remove_trigger(&humid_st->common_attributes);
return ret;
}
/* Function to deinitialize the processing for usage id */
static int hid_humidity_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct hid_humidity_state *humid_st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY);
hid_sensor_remove_trigger(&humid_st->common_attributes);
return 0;
}
static const struct platform_device_id hid_humidity_ids[] = {
{
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
.name = "HID-SENSOR-200032",
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, hid_humidity_ids);
static struct platform_driver hid_humidity_platform_driver = {
.id_table = hid_humidity_ids,
.driver = {
.name = KBUILD_MODNAME,
.pm = &hid_sensor_pm_ops,
},
.probe = hid_humidity_probe,
.remove = hid_humidity_remove,
};
module_platform_driver(hid_humidity_platform_driver);
MODULE_DESCRIPTION("HID Environmental humidity sensor");
MODULE_AUTHOR("Song Hongyan <hongyan.song@intel.com>");
MODULE_LICENSE("GPL v2");
...@@ -41,7 +41,7 @@ static const struct iio_trigger_ops hts221_trigger_ops = { ...@@ -41,7 +41,7 @@ static const struct iio_trigger_ops hts221_trigger_ops = {
static irqreturn_t hts221_trigger_handler_thread(int irq, void *private) static irqreturn_t hts221_trigger_handler_thread(int irq, void *private)
{ {
struct hts221_hw *hw = (struct hts221_hw *)private; struct hts221_hw *hw = private;
u8 status; u8 status;
int err; int err;
......
...@@ -113,6 +113,12 @@ static const struct inv_mpu6050_hw hw_info[] = { ...@@ -113,6 +113,12 @@ static const struct inv_mpu6050_hw hw_info[] = {
.reg = &reg_set_6050, .reg = &reg_set_6050,
.config = &chip_config_6050, .config = &chip_config_6050,
}, },
{
.whoami = INV_MPU9250_WHOAMI_VALUE,
.name = "MPU9250",
.reg = &reg_set_6500,
.config = &chip_config_6050,
},
{ {
.whoami = INV_ICM20608_WHOAMI_VALUE, .whoami = INV_ICM20608_WHOAMI_VALUE,
.name = "ICM20608", .name = "ICM20608",
......
...@@ -178,6 +178,7 @@ static const struct i2c_device_id inv_mpu_id[] = { ...@@ -178,6 +178,7 @@ static const struct i2c_device_id inv_mpu_id[] = {
{"mpu6050", INV_MPU6050}, {"mpu6050", INV_MPU6050},
{"mpu6500", INV_MPU6500}, {"mpu6500", INV_MPU6500},
{"mpu9150", INV_MPU9150}, {"mpu9150", INV_MPU9150},
{"mpu9250", INV_MPU9250},
{"icm20608", INV_ICM20608}, {"icm20608", INV_ICM20608},
{} {}
}; };
...@@ -197,6 +198,10 @@ static const struct of_device_id inv_of_match[] = { ...@@ -197,6 +198,10 @@ static const struct of_device_id inv_of_match[] = {
.compatible = "invensense,mpu9150", .compatible = "invensense,mpu9150",
.data = (void *)INV_MPU9150 .data = (void *)INV_MPU9150
}, },
{
.compatible = "invensense,mpu9250",
.data = (void *)INV_MPU9250
},
{ {
.compatible = "invensense,icm20608", .compatible = "invensense,icm20608",
.data = (void *)INV_ICM20608 .data = (void *)INV_ICM20608
......
...@@ -70,6 +70,7 @@ enum inv_devices { ...@@ -70,6 +70,7 @@ enum inv_devices {
INV_MPU6500, INV_MPU6500,
INV_MPU6000, INV_MPU6000,
INV_MPU9150, INV_MPU9150,
INV_MPU9250,
INV_ICM20608, INV_ICM20608,
INV_NUM_PARTS INV_NUM_PARTS
}; };
...@@ -226,6 +227,7 @@ struct inv_mpu6050_state { ...@@ -226,6 +227,7 @@ struct inv_mpu6050_state {
#define INV_MPU6050_WHOAMI_VALUE 0x68 #define INV_MPU6050_WHOAMI_VALUE 0x68
#define INV_MPU6500_WHOAMI_VALUE 0x70 #define INV_MPU6500_WHOAMI_VALUE 0x70
#define INV_MPU9150_WHOAMI_VALUE 0x68 #define INV_MPU9150_WHOAMI_VALUE 0x68
#define INV_MPU9250_WHOAMI_VALUE 0x71
#define INV_ICM20608_WHOAMI_VALUE 0xAF #define INV_ICM20608_WHOAMI_VALUE 0xAF
/* scan element definition */ /* scan element definition */
......
...@@ -82,6 +82,7 @@ static const struct spi_device_id inv_mpu_id[] = { ...@@ -82,6 +82,7 @@ static const struct spi_device_id inv_mpu_id[] = {
{"mpu6000", INV_MPU6000}, {"mpu6000", INV_MPU6000},
{"mpu6500", INV_MPU6500}, {"mpu6500", INV_MPU6500},
{"mpu9150", INV_MPU9150}, {"mpu9150", INV_MPU9150},
{"mpu9250", INV_MPU9250},
{"icm20608", INV_ICM20608}, {"icm20608", INV_ICM20608},
{} {}
}; };
......
...@@ -364,7 +364,7 @@ static int st_lsm6dsx_update_fifo(struct iio_dev *iio_dev, bool enable) ...@@ -364,7 +364,7 @@ static int st_lsm6dsx_update_fifo(struct iio_dev *iio_dev, bool enable)
static irqreturn_t st_lsm6dsx_handler_irq(int irq, void *private) static irqreturn_t st_lsm6dsx_handler_irq(int irq, void *private)
{ {
struct st_lsm6dsx_hw *hw = (struct st_lsm6dsx_hw *)private; struct st_lsm6dsx_hw *hw = private;
struct st_lsm6dsx_sensor *sensor; struct st_lsm6dsx_sensor *sensor;
int i; int i;
...@@ -388,7 +388,7 @@ static irqreturn_t st_lsm6dsx_handler_irq(int irq, void *private) ...@@ -388,7 +388,7 @@ static irqreturn_t st_lsm6dsx_handler_irq(int irq, void *private)
static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private) static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private)
{ {
struct st_lsm6dsx_hw *hw = (struct st_lsm6dsx_hw *)private; struct st_lsm6dsx_hw *hw = private;
int count; int count;
mutex_lock(&hw->fifo_lock); mutex_lock(&hw->fifo_lock);
......
...@@ -308,32 +308,40 @@ static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor, ...@@ -308,32 +308,40 @@ static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor,
return 0; return 0;
} }
static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 odr) static int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u16 odr,
u8 *val)
{ {
enum st_lsm6dsx_sensor_id id = sensor->id; int i;
int i, err;
u8 val;
for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++)
if (st_lsm6dsx_odr_table[id].odr_avl[i].hz == odr) if (st_lsm6dsx_odr_table[sensor->id].odr_avl[i].hz == odr)
break; break;
if (i == ST_LSM6DSX_ODR_LIST_SIZE) if (i == ST_LSM6DSX_ODR_LIST_SIZE)
return -EINVAL; return -EINVAL;
val = st_lsm6dsx_odr_table[id].odr_avl[i].val; *val = st_lsm6dsx_odr_table[sensor->id].odr_avl[i].val;
err = st_lsm6dsx_write_with_mask(sensor->hw,
st_lsm6dsx_odr_table[id].reg.addr,
st_lsm6dsx_odr_table[id].reg.mask,
val);
if (err < 0)
return err;
sensor->odr = odr; sensor->odr = odr;
return 0; return 0;
} }
static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 odr)
{
enum st_lsm6dsx_sensor_id id = sensor->id;
int err;
u8 val;
err = st_lsm6dsx_check_odr(sensor, odr, &val);
if (err < 0)
return err;
return st_lsm6dsx_write_with_mask(sensor->hw,
st_lsm6dsx_odr_table[id].reg.addr,
st_lsm6dsx_odr_table[id].reg.mask,
val);
}
int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor) int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor)
{ {
int err; int err;
...@@ -436,9 +444,12 @@ static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev, ...@@ -436,9 +444,12 @@ static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev,
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
err = st_lsm6dsx_set_full_scale(sensor, val2); err = st_lsm6dsx_set_full_scale(sensor, val2);
break; break;
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ: {
err = st_lsm6dsx_set_odr(sensor, val); u8 data;
err = st_lsm6dsx_check_odr(sensor, val, &data);
break; break;
}
default: default:
err = -EINVAL; err = -EINVAL;
break; break;
......
...@@ -405,4 +405,14 @@ config VEML6070 ...@@ -405,4 +405,14 @@ config VEML6070
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called veml6070. module will be called veml6070.
config VL6180
tristate "VL6180 ALS, range and proximity sensor"
depends on I2C
help
Say Y here if you want to build a driver for the STMicroelectronics
VL6180 combined ambient light, range and proximity sensor.
To compile this driver as a module, choose M here: the
module will be called vl6180.
endmenu endmenu
...@@ -38,3 +38,4 @@ obj-$(CONFIG_TSL4531) += tsl4531.o ...@@ -38,3 +38,4 @@ obj-$(CONFIG_TSL4531) += tsl4531.o
obj-$(CONFIG_US5182D) += us5182d.o obj-$(CONFIG_US5182D) += us5182d.o
obj-$(CONFIG_VCNL4000) += vcnl4000.o obj-$(CONFIG_VCNL4000) += vcnl4000.o
obj-$(CONFIG_VEML6070) += veml6070.o obj-$(CONFIG_VEML6070) += veml6070.o
obj-$(CONFIG_VL6180) += vl6180.o
...@@ -343,7 +343,7 @@ static struct attribute *apds9960_attributes[] = { ...@@ -343,7 +343,7 @@ static struct attribute *apds9960_attributes[] = {
NULL, NULL,
}; };
static struct attribute_group apds9960_attribute_group = { static const struct attribute_group apds9960_attribute_group = {
.attrs = apds9960_attributes, .attrs = apds9960_attributes,
}; };
......
...@@ -212,7 +212,7 @@ static struct attribute *bh1750_attributes[] = { ...@@ -212,7 +212,7 @@ static struct attribute *bh1750_attributes[] = {
NULL, NULL,
}; };
static struct attribute_group bh1750_attribute_group = { static const struct attribute_group bh1750_attribute_group = {
.attrs = bh1750_attributes, .attrs = bh1750_attributes,
}; };
......
...@@ -690,7 +690,7 @@ static struct attribute *lm3533_als_event_attributes[] = { ...@@ -690,7 +690,7 @@ static struct attribute *lm3533_als_event_attributes[] = {
NULL NULL
}; };
static struct attribute_group lm3533_als_event_attribute_group = { static const struct attribute_group lm3533_als_event_attribute_group = {
.attrs = lm3533_als_event_attributes .attrs = lm3533_als_event_attributes
}; };
...@@ -714,7 +714,7 @@ static struct attribute *lm3533_als_attributes[] = { ...@@ -714,7 +714,7 @@ static struct attribute *lm3533_als_attributes[] = {
NULL NULL
}; };
static struct attribute_group lm3533_als_attribute_group = { static const struct attribute_group lm3533_als_attribute_group = {
.attrs = lm3533_als_attributes .attrs = lm3533_als_attributes
}; };
......
This diff is collapsed.
...@@ -751,7 +751,7 @@ static void zpa2326_suspend(struct iio_dev *indio_dev) ...@@ -751,7 +751,7 @@ static void zpa2326_suspend(struct iio_dev *indio_dev)
*/ */
static irqreturn_t zpa2326_handle_irq(int irq, void *data) static irqreturn_t zpa2326_handle_irq(int irq, void *data)
{ {
struct iio_dev *indio_dev = (struct iio_dev *)data; struct iio_dev *indio_dev = data;
if (iio_buffer_enabled(indio_dev)) { if (iio_buffer_enabled(indio_dev)) {
/* Timestamping needed for buffered sampling only. */ /* Timestamping needed for buffered sampling only. */
...@@ -790,7 +790,7 @@ static irqreturn_t zpa2326_handle_irq(int irq, void *data) ...@@ -790,7 +790,7 @@ static irqreturn_t zpa2326_handle_irq(int irq, void *data)
*/ */
static irqreturn_t zpa2326_handle_threaded_irq(int irq, void *data) static irqreturn_t zpa2326_handle_threaded_irq(int irq, void *data)
{ {
struct iio_dev *indio_dev = (struct iio_dev *)data; struct iio_dev *indio_dev = data;
struct zpa2326_private *priv = iio_priv(indio_dev); struct zpa2326_private *priv = iio_priv(indio_dev);
unsigned int val; unsigned int val;
bool cont; bool cont;
......
...@@ -155,7 +155,7 @@ static struct attribute *as3935_attributes[] = { ...@@ -155,7 +155,7 @@ static struct attribute *as3935_attributes[] = {
NULL, NULL,
}; };
static struct attribute_group as3935_attribute_group = { static const struct attribute_group as3935_attribute_group = {
.attrs = as3935_attributes, .attrs = as3935_attributes,
}; };
......
...@@ -203,17 +203,14 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, ...@@ -203,17 +203,14 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_CALIBBIAS:
bits = 14; bits = 14;
mutex_lock(&indio_dev->mlock);
addr = adis16203_addresses[chan->scan_index]; addr = adis16203_addresses[chan->scan_index];
ret = adis_read_reg_16(st, addr, &val16); ret = adis_read_reg_16(st, addr, &val16);
if (ret) { if (ret) {
mutex_unlock(&indio_dev->mlock);
return ret; return ret;
} }
val16 &= (1 << bits) - 1; val16 &= (1 << bits) - 1;
val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
*val = val16; *val = val16;
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT; return IIO_VAL_INT;
default: default:
return -EINVAL; return -EINVAL;
......
...@@ -255,9 +255,8 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, ...@@ -255,9 +255,8 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
} }
addr = adis16209_addresses[chan->scan_index][0]; addr = adis16209_addresses[chan->scan_index][0];
ret = adis_read_reg_16(st, addr, &val16); ret = adis_read_reg_16(st, addr, &val16);
if (ret) { if (ret)
return ret; return ret;
}
val16 &= (1 << bits) - 1; val16 &= (1 << bits) - 1;
val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
*val = val16; *val = val16;
......
...@@ -290,9 +290,8 @@ static int adis16240_read_raw(struct iio_dev *indio_dev, ...@@ -290,9 +290,8 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
bits = 10; bits = 10;
addr = adis16240_addresses[chan->scan_index][0]; addr = adis16240_addresses[chan->scan_index][0];
ret = adis_read_reg_16(st, addr, &val16); ret = adis_read_reg_16(st, addr, &val16);
if (ret) { if (ret)
return ret; return ret;
}
val16 &= (1 << bits) - 1; val16 &= (1 << bits) - 1;
val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
*val = val16; *val = val16;
...@@ -301,9 +300,8 @@ static int adis16240_read_raw(struct iio_dev *indio_dev, ...@@ -301,9 +300,8 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
bits = 10; bits = 10;
addr = adis16240_addresses[chan->scan_index][1]; addr = adis16240_addresses[chan->scan_index][1];
ret = adis_read_reg_16(st, addr, &val16); ret = adis_read_reg_16(st, addr, &val16);
if (ret) { if (ret)
return ret; return ret;
}
val16 &= (1 << bits) - 1; val16 &= (1 << bits) - 1;
val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
*val = val16; *val = val16;
......
...@@ -560,7 +560,7 @@ static int ad7280_attr_init(struct ad7280_state *st) ...@@ -560,7 +560,7 @@ static int ad7280_attr_init(struct ad7280_state *st)
st->iio_attr[cnt].address = st->iio_attr[cnt].address =
AD7280A_DEVADDR(dev) << 8 | ch; AD7280A_DEVADDR(dev) << 8 | ch;
st->iio_attr[cnt].dev_attr.attr.mode = st->iio_attr[cnt].dev_attr.attr.mode =
S_IWUSR | S_IRUGO; 0644;
st->iio_attr[cnt].dev_attr.show = st->iio_attr[cnt].dev_attr.show =
ad7280_show_balance_sw; ad7280_show_balance_sw;
st->iio_attr[cnt].dev_attr.store = st->iio_attr[cnt].dev_attr.store =
...@@ -577,7 +577,7 @@ static int ad7280_attr_init(struct ad7280_state *st) ...@@ -577,7 +577,7 @@ static int ad7280_attr_init(struct ad7280_state *st)
AD7280A_DEVADDR(dev) << 8 | AD7280A_DEVADDR(dev) << 8 |
(AD7280A_CB1_TIMER + ch); (AD7280A_CB1_TIMER + ch);
st->iio_attr[cnt].dev_attr.attr.mode = st->iio_attr[cnt].dev_attr.attr.mode =
S_IWUSR | S_IRUGO; 0644;
st->iio_attr[cnt].dev_attr.show = st->iio_attr[cnt].dev_attr.show =
ad7280_show_balance_timer; ad7280_show_balance_timer;
st->iio_attr[cnt].dev_attr.store = st->iio_attr[cnt].dev_attr.store =
...@@ -746,26 +746,26 @@ static irqreturn_t ad7280_event_handler(int irq, void *private) ...@@ -746,26 +746,26 @@ static irqreturn_t ad7280_event_handler(int irq, void *private)
static IIO_DEVICE_ATTR_NAMED(in_thresh_low_value, static IIO_DEVICE_ATTR_NAMED(in_thresh_low_value,
in_voltage-voltage_thresh_low_value, in_voltage-voltage_thresh_low_value,
S_IRUGO | S_IWUSR, 0644,
ad7280_read_channel_config, ad7280_read_channel_config,
ad7280_write_channel_config, ad7280_write_channel_config,
AD7280A_CELL_UNDERVOLTAGE); AD7280A_CELL_UNDERVOLTAGE);
static IIO_DEVICE_ATTR_NAMED(in_thresh_high_value, static IIO_DEVICE_ATTR_NAMED(in_thresh_high_value,
in_voltage-voltage_thresh_high_value, in_voltage-voltage_thresh_high_value,
S_IRUGO | S_IWUSR, 0644,
ad7280_read_channel_config, ad7280_read_channel_config,
ad7280_write_channel_config, ad7280_write_channel_config,
AD7280A_CELL_OVERVOLTAGE); AD7280A_CELL_OVERVOLTAGE);
static IIO_DEVICE_ATTR(in_temp_thresh_low_value, static IIO_DEVICE_ATTR(in_temp_thresh_low_value,
S_IRUGO | S_IWUSR, 0644,
ad7280_read_channel_config, ad7280_read_channel_config,
ad7280_write_channel_config, ad7280_write_channel_config,
AD7280A_AUX_ADC_UNDERVOLTAGE); AD7280A_AUX_ADC_UNDERVOLTAGE);
static IIO_DEVICE_ATTR(in_temp_thresh_high_value, static IIO_DEVICE_ATTR(in_temp_thresh_high_value,
S_IRUGO | S_IWUSR, 0644,
ad7280_read_channel_config, ad7280_read_channel_config,
ad7280_write_channel_config, ad7280_write_channel_config,
AD7280A_AUX_ADC_OVERVOLTAGE); AD7280A_AUX_ADC_OVERVOLTAGE);
......
...@@ -208,7 +208,7 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, ...@@ -208,7 +208,7 @@ static int ad7606_write_raw(struct iio_dev *indio_dev,
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
ret = -EINVAL; ret = -EINVAL;
mutex_lock(&indio_dev->mlock); mutex_lock(&st->lock);
for (i = 0; i < ARRAY_SIZE(scale_avail); i++) for (i = 0; i < ARRAY_SIZE(scale_avail); i++)
if (val2 == scale_avail[i][1]) { if (val2 == scale_avail[i][1]) {
gpiod_set_value(st->gpio_range, i); gpiod_set_value(st->gpio_range, i);
...@@ -217,7 +217,7 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, ...@@ -217,7 +217,7 @@ static int ad7606_write_raw(struct iio_dev *indio_dev,
ret = 0; ret = 0;
break; break;
} }
mutex_unlock(&indio_dev->mlock); mutex_unlock(&st->lock);
return ret; return ret;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO: case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
...@@ -231,11 +231,11 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, ...@@ -231,11 +231,11 @@ static int ad7606_write_raw(struct iio_dev *indio_dev,
values[1] = (ret >> 1) & 1; values[1] = (ret >> 1) & 1;
values[2] = (ret >> 2) & 1; values[2] = (ret >> 2) & 1;
mutex_lock(&indio_dev->mlock); mutex_lock(&st->lock);
gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc, gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc,
values); values);
st->oversampling = val; st->oversampling = val;
mutex_unlock(&indio_dev->mlock); mutex_unlock(&st->lock);
return 0; return 0;
default: default:
...@@ -413,6 +413,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, ...@@ -413,6 +413,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
st = iio_priv(indio_dev); st = iio_priv(indio_dev);
st->dev = dev; st->dev = dev;
mutex_init(&st->lock);
st->bops = bops; st->bops = bops;
st->base_address = base_address; st->base_address = base_address;
/* tied to logic low, analog input range is +/- 5V */ /* tied to logic low, analog input range is +/- 5V */
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
* @name: identification string for chip * @name: identification string for chip
* @channels: channel specification * @channels: channel specification
* @num_channels: number of channels * @num_channels: number of channels
* @lock protect sensor state
*/ */
struct ad7606_chip_info { struct ad7606_chip_info {
...@@ -23,6 +24,7 @@ struct ad7606_chip_info { ...@@ -23,6 +24,7 @@ struct ad7606_chip_info {
/** /**
* struct ad7606_state - driver instance specific data * struct ad7606_state - driver instance specific data
* @lock protect sensor state
*/ */
struct ad7606_state { struct ad7606_state {
...@@ -37,6 +39,7 @@ struct ad7606_state { ...@@ -37,6 +39,7 @@ struct ad7606_state {
bool done; bool done;
void __iomem *base_address; void __iomem *base_address;
struct mutex lock; /* protect sensor state */
struct gpio_desc *gpio_convst; struct gpio_desc *gpio_convst;
struct gpio_desc *gpio_reset; struct gpio_desc *gpio_reset;
struct gpio_desc *gpio_range; struct gpio_desc *gpio_range;
......
...@@ -244,7 +244,6 @@ static ssize_t _adt7316_store_enabled(struct adt7316_chip_info *chip, ...@@ -244,7 +244,6 @@ static ssize_t _adt7316_store_enabled(struct adt7316_chip_info *chip,
chip->config1 = config1; chip->config1 = config1;
return ret; return ret;
} }
static ssize_t adt7316_store_enabled(struct device *dev, static ssize_t adt7316_store_enabled(struct device *dev,
...@@ -434,7 +433,6 @@ static ssize_t adt7316_store_ad_channel(struct device *dev, ...@@ -434,7 +433,6 @@ static ssize_t adt7316_store_ad_channel(struct device *dev,
config2 = chip->config2 & (~ADT7316_AD_SINGLE_CH_MASK); config2 = chip->config2 & (~ADT7316_AD_SINGLE_CH_MASK);
} }
config2 |= data; config2 |= data;
ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2); ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2);
...@@ -725,7 +723,6 @@ static IIO_DEVICE_ATTR(AIN_internal_Vref, 0644, ...@@ -725,7 +723,6 @@ static IIO_DEVICE_ATTR(AIN_internal_Vref, 0644,
adt7316_store_AIN_internal_Vref, adt7316_store_AIN_internal_Vref,
0); 0);
static ssize_t adt7316_show_enable_prop_DACA(struct device *dev, static ssize_t adt7316_show_enable_prop_DACA(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
...@@ -925,7 +922,6 @@ static ssize_t adt7316_show_all_DAC_update_modes(struct device *dev, ...@@ -925,7 +922,6 @@ static ssize_t adt7316_show_all_DAC_update_modes(struct device *dev,
static IIO_DEVICE_ATTR(all_DAC_update_modes, 0444, static IIO_DEVICE_ATTR(all_DAC_update_modes, 0444,
adt7316_show_all_DAC_update_modes, NULL, 0); adt7316_show_all_DAC_update_modes, NULL, 0);
static ssize_t adt7316_store_update_DAC(struct device *dev, static ssize_t adt7316_store_update_DAC(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, const char *buf,
...@@ -1867,6 +1863,7 @@ static ssize_t adt7316_set_int_mask(struct device *dev, ...@@ -1867,6 +1863,7 @@ static ssize_t adt7316_set_int_mask(struct device *dev,
return len; return len;
} }
static inline ssize_t adt7316_show_ad_bound(struct device *dev, static inline ssize_t adt7316_show_ad_bound(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
......
...@@ -232,7 +232,7 @@ static int ad7150_write_event_config(struct iio_dev *indio_dev, ...@@ -232,7 +232,7 @@ static int ad7150_write_event_config(struct iio_dev *indio_dev,
if (ret < 0) if (ret < 0)
goto error_ret; goto error_ret;
cfg = ret & ~((0x03 << 5) | (0x1 << 7)); cfg = ret & ~((0x03 << 5) | BIT(7));
switch (type) { switch (type) {
case IIO_EV_TYPE_MAG_ADAPTIVE: case IIO_EV_TYPE_MAG_ADAPTIVE:
......
...@@ -244,6 +244,7 @@ static int ad7152_write_raw_samp_freq(struct device *dev, int val) ...@@ -244,6 +244,7 @@ static int ad7152_write_raw_samp_freq(struct device *dev, int val)
return ret; return ret;
} }
static int ad7152_write_raw(struct iio_dev *indio_dev, static int ad7152_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, struct iio_chan_spec const *chan,
int val, int val,
......
...@@ -45,10 +45,10 @@ ...@@ -45,10 +45,10 @@
#define AD7746_STATUS_RDYCAP BIT(0) #define AD7746_STATUS_RDYCAP BIT(0)
/* Capacitive Channel Setup Register Bit Designations (AD7746_REG_CAP_SETUP) */ /* Capacitive Channel Setup Register Bit Designations (AD7746_REG_CAP_SETUP) */
#define AD7746_CAPSETUP_CAPEN (1 << 7) #define AD7746_CAPSETUP_CAPEN BIT(7)
#define AD7746_CAPSETUP_CIN2 (1 << 6) /* AD7746 only */ #define AD7746_CAPSETUP_CIN2 BIT(6) /* AD7746 only */
#define AD7746_CAPSETUP_CAPDIFF (1 << 5) #define AD7746_CAPSETUP_CAPDIFF BIT(5)
#define AD7746_CAPSETUP_CACHOP (1 << 0) #define AD7746_CAPSETUP_CACHOP BIT(0)
/* Voltage/Temperature Setup Register Bit Designations (AD7746_REG_VT_SETUP) */ /* Voltage/Temperature Setup Register Bit Designations (AD7746_REG_VT_SETUP) */
#define AD7746_VTSETUP_VTEN (1 << 7) #define AD7746_VTSETUP_VTEN (1 << 7)
...@@ -56,9 +56,9 @@ ...@@ -56,9 +56,9 @@
#define AD7746_VTSETUP_VTMD_EXT_TEMP (1 << 5) #define AD7746_VTSETUP_VTMD_EXT_TEMP (1 << 5)
#define AD7746_VTSETUP_VTMD_VDD_MON (2 << 5) #define AD7746_VTSETUP_VTMD_VDD_MON (2 << 5)
#define AD7746_VTSETUP_VTMD_EXT_VIN (3 << 5) #define AD7746_VTSETUP_VTMD_EXT_VIN (3 << 5)
#define AD7746_VTSETUP_EXTREF (1 << 4) #define AD7746_VTSETUP_EXTREF BIT(4)
#define AD7746_VTSETUP_VTSHORT (1 << 1) #define AD7746_VTSETUP_VTSHORT BIT(1)
#define AD7746_VTSETUP_VTCHOP (1 << 0) #define AD7746_VTSETUP_VTCHOP BIT(0)
/* Excitation Setup Register Bit Designations (AD7746_REG_EXC_SETUP) */ /* Excitation Setup Register Bit Designations (AD7746_REG_EXC_SETUP) */
#define AD7746_EXCSETUP_CLKCTRL BIT(7) #define AD7746_EXCSETUP_CLKCTRL BIT(7)
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
#define AD7746_CONF_MODE_GAIN_CAL (6 << 0) #define AD7746_CONF_MODE_GAIN_CAL (6 << 0)
/* CAPDAC Register Bit Designations (AD7746_REG_CAPDACx) */ /* CAPDAC Register Bit Designations (AD7746_REG_CAPDACx) */
#define AD7746_CAPDAC_DACEN (1 << 7) #define AD7746_CAPDAC_DACEN BIT(7)
#define AD7746_CAPDAC_DACP(x) ((x) & 0x7F) #define AD7746_CAPDAC_DACP(x) ((x) & 0x7F)
/* /*
......
...@@ -250,22 +250,22 @@ static ssize_t ad9832_write(struct device *dev, struct device_attribute *attr, ...@@ -250,22 +250,22 @@ static ssize_t ad9832_write(struct device *dev, struct device_attribute *attr,
* see dds.h for further information * see dds.h for further information
*/ */
static IIO_DEV_ATTR_FREQ(0, 0, S_IWUSR, NULL, ad9832_write, AD9832_FREQ0HM); static IIO_DEV_ATTR_FREQ(0, 0, 0200, NULL, ad9832_write, AD9832_FREQ0HM);
static IIO_DEV_ATTR_FREQ(0, 1, S_IWUSR, NULL, ad9832_write, AD9832_FREQ1HM); static IIO_DEV_ATTR_FREQ(0, 1, 0200, NULL, ad9832_write, AD9832_FREQ1HM);
static IIO_DEV_ATTR_FREQSYMBOL(0, S_IWUSR, NULL, ad9832_write, AD9832_FREQ_SYM); static IIO_DEV_ATTR_FREQSYMBOL(0, 0200, NULL, ad9832_write, AD9832_FREQ_SYM);
static IIO_CONST_ATTR_FREQ_SCALE(0, "1"); /* 1Hz */ static IIO_CONST_ATTR_FREQ_SCALE(0, "1"); /* 1Hz */
static IIO_DEV_ATTR_PHASE(0, 0, S_IWUSR, NULL, ad9832_write, AD9832_PHASE0H); static IIO_DEV_ATTR_PHASE(0, 0, 0200, NULL, ad9832_write, AD9832_PHASE0H);
static IIO_DEV_ATTR_PHASE(0, 1, S_IWUSR, NULL, ad9832_write, AD9832_PHASE1H); static IIO_DEV_ATTR_PHASE(0, 1, 0200, NULL, ad9832_write, AD9832_PHASE1H);
static IIO_DEV_ATTR_PHASE(0, 2, S_IWUSR, NULL, ad9832_write, AD9832_PHASE2H); static IIO_DEV_ATTR_PHASE(0, 2, 0200, NULL, ad9832_write, AD9832_PHASE2H);
static IIO_DEV_ATTR_PHASE(0, 3, S_IWUSR, NULL, ad9832_write, AD9832_PHASE3H); static IIO_DEV_ATTR_PHASE(0, 3, 0200, NULL, ad9832_write, AD9832_PHASE3H);
static IIO_DEV_ATTR_PHASESYMBOL(0, S_IWUSR, NULL, static IIO_DEV_ATTR_PHASESYMBOL(0, 0200, NULL,
ad9832_write, AD9832_PHASE_SYM); ad9832_write, AD9832_PHASE_SYM);
static IIO_CONST_ATTR_PHASE_SCALE(0, "0.0015339808"); /* 2PI/2^12 rad*/ static IIO_CONST_ATTR_PHASE_SCALE(0, "0.0015339808"); /* 2PI/2^12 rad*/
static IIO_DEV_ATTR_PINCONTROL_EN(0, S_IWUSR, NULL, static IIO_DEV_ATTR_PINCONTROL_EN(0, 0200, NULL,
ad9832_write, AD9832_PINCTRL_EN); ad9832_write, AD9832_PINCTRL_EN);
static IIO_DEV_ATTR_OUT_ENABLE(0, S_IWUSR, NULL, static IIO_DEV_ATTR_OUT_ENABLE(0, 0200, NULL,
ad9832_write, AD9832_OUTPUT_EN); ad9832_write, AD9832_OUTPUT_EN);
static struct attribute *ad9832_attributes[] = { static struct attribute *ad9832_attributes[] = {
......
...@@ -40,25 +40,20 @@ struct adis16060_state { ...@@ -40,25 +40,20 @@ struct adis16060_state {
static struct iio_dev *adis16060_iio_dev; static struct iio_dev *adis16060_iio_dev;
static int adis16060_spi_write(struct iio_dev *indio_dev, u8 val) static int adis16060_spi_write_then_read(struct iio_dev *indio_dev,
u8 conf, u16 *val)
{ {
int ret; int ret;
struct adis16060_state *st = iio_priv(indio_dev); struct adis16060_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock); mutex_lock(&st->buf_lock);
st->buf[2] = val; /* The last 8 bits clocked in are latched */ st->buf[2] = conf; /* The last 8 bits clocked in are latched */
ret = spi_write(st->us_w, st->buf, 3); ret = spi_write(st->us_w, st->buf, 3);
mutex_unlock(&st->buf_lock);
if (ret < 0) {
mutex_unlock(&st->buf_lock);
return ret; return ret;
} }
static int adis16060_spi_read(struct iio_dev *indio_dev, u16 *val)
{
int ret;
struct adis16060_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
ret = spi_read(st->us_r, st->buf, 3); ret = spi_read(st->us_r, st->buf, 3);
...@@ -86,17 +81,11 @@ static int adis16060_read_raw(struct iio_dev *indio_dev, ...@@ -86,17 +81,11 @@ static int adis16060_read_raw(struct iio_dev *indio_dev,
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
/* Take the iio_dev status lock */ ret = adis16060_spi_write_then_read(indio_dev,
mutex_lock(&indio_dev->mlock); chan->address, &tval);
ret = adis16060_spi_write(indio_dev, chan->address);
if (ret < 0)
goto out_unlock;
ret = adis16060_spi_read(indio_dev, &tval);
if (ret < 0) if (ret < 0)
goto out_unlock; return ret;
mutex_unlock(&indio_dev->mlock);
*val = tval; *val = tval;
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_OFFSET: case IIO_CHAN_INFO_OFFSET:
...@@ -110,10 +99,6 @@ static int adis16060_read_raw(struct iio_dev *indio_dev, ...@@ -110,10 +99,6 @@ static int adis16060_read_raw(struct iio_dev *indio_dev,
} }
return -EINVAL; return -EINVAL;
out_unlock:
mutex_unlock(&indio_dev->mlock);
return ret;
} }
static const struct iio_info adis16060_info = { static const struct iio_info adis16060_info = {
......
...@@ -854,7 +854,7 @@ void tsl2x7x_prox_calculate(int *data, int length, ...@@ -854,7 +854,7 @@ void tsl2x7x_prox_calculate(int *data, int length,
tmp = data[i] - statP->mean; tmp = data[i] - statP->mean;
sample_sum += tmp * tmp; sample_sum += tmp * tmp;
} }
statP->stddev = int_sqrt((long)sample_sum) / length; statP->stddev = int_sqrt((long)sample_sum / length);
} }
/** /**
...@@ -1676,7 +1676,7 @@ static const struct attribute_group tsl2X7X_device_attr_group_tbl[] = { ...@@ -1676,7 +1676,7 @@ static const struct attribute_group tsl2X7X_device_attr_group_tbl[] = {
}, },
}; };
static struct attribute_group tsl2X7X_event_attr_group_tbl[] = { static const struct attribute_group tsl2X7X_event_attr_group_tbl[] = {
[ALS] = { [ALS] = {
.attrs = tsl2X7X_ALS_event_attrs, .attrs = tsl2X7X_ALS_event_attrs,
.name = "events", .name = "events",
......
...@@ -6,18 +6,17 @@ ...@@ -6,18 +6,17 @@
* Licensed under the GPL-2 or later. * Licensed under the GPL-2 or later.
*/ */
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
#include "meter.h" #include "meter.h"
...@@ -97,7 +96,7 @@ ...@@ -97,7 +96,7 @@
/** /**
* struct ade7754_state - device instance specific data * struct ade7754_state - device instance specific data
* @us: actual spi_device * @us: actual spi_device
* @buf_lock: mutex to protect tx and rx * @buf_lock: mutex to protect tx, rx and write frequency
* @tx: transmit buffer * @tx: transmit buffer
* @rx: receive buffer * @rx: receive buffer
**/ **/
...@@ -108,17 +107,25 @@ struct ade7754_state { ...@@ -108,17 +107,25 @@ struct ade7754_state {
u8 rx[ADE7754_MAX_RX]; u8 rx[ADE7754_MAX_RX];
}; };
static int ade7754_spi_write_reg_8(struct device *dev, u8 reg_address, u8 val) /* Unlocked version of ade7754_spi_write_reg_8 function */
static int __ade7754_spi_write_reg_8(struct device *dev, u8 reg_address, u8 val)
{ {
int ret;
struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7754_state *st = iio_priv(indio_dev); struct ade7754_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = ADE7754_WRITE_REG(reg_address); st->tx[0] = ADE7754_WRITE_REG(reg_address);
st->tx[1] = val; st->tx[1] = val;
return spi_write(st->us, st->tx, 2);
}
static int ade7754_spi_write_reg_8(struct device *dev, u8 reg_address, u8 val)
{
int ret;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7754_state *st = iio_priv(indio_dev);
ret = spi_write(st->us, st->tx, 2); mutex_lock(&st->buf_lock);
ret = __ade7754_spi_write_reg_8(dev, reg_address, val);
mutex_unlock(&st->buf_lock); mutex_unlock(&st->buf_lock);
return ret; return ret;
...@@ -513,7 +520,7 @@ static ssize_t ade7754_write_frequency(struct device *dev, ...@@ -513,7 +520,7 @@ static ssize_t ade7754_write_frequency(struct device *dev,
if (!val) if (!val)
return -EINVAL; return -EINVAL;
mutex_lock(&indio_dev->mlock); mutex_lock(&st->buf_lock);
t = 26000 / val; t = 26000 / val;
if (t > 0) if (t > 0)
...@@ -531,10 +538,10 @@ static ssize_t ade7754_write_frequency(struct device *dev, ...@@ -531,10 +538,10 @@ static ssize_t ade7754_write_frequency(struct device *dev,
reg &= ~(3 << 3); reg &= ~(3 << 3);
reg |= t << 3; reg |= t << 3;
ret = ade7754_spi_write_reg_8(dev, ADE7754_WAVMODE, reg); ret = __ade7754_spi_write_reg_8(dev, ADE7754_WAVMODE, reg);
out: out:
mutex_unlock(&indio_dev->mlock); mutex_unlock(&st->buf_lock);
return ret ? ret : len; return ret ? ret : len;
} }
......
...@@ -49,6 +49,10 @@ ...@@ -49,6 +49,10 @@
#define HID_USAGE_SENSOR_TEMPERATURE 0x200033 #define HID_USAGE_SENSOR_TEMPERATURE 0x200033
#define HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE 0x200434 #define HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE 0x200434
/* humidity */
#define HID_USAGE_SENSOR_HUMIDITY 0x200032
#define HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY 0x200433
/* Gyro 3D: (200076) */ /* Gyro 3D: (200076) */
#define HID_USAGE_SENSOR_GYRO_3D 0x200076 #define HID_USAGE_SENSOR_GYRO_3D 0x200076
#define HID_USAGE_SENSOR_DATA_ANGL_VELOCITY 0x200456 #define HID_USAGE_SENSOR_DATA_ANGL_VELOCITY 0x200456
......
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