staging tree merge for 3.12-rc1
Here's the bit staging tree pull request for 3.12-rc1. Lots of staging driver updates, and fixes. Lustre is finally enabled in the build, and lots of cleanup started happening in it. There's a new wireless driver in here, and 2 new TTY drivers, which cause the overall lines added/removed to be quite large on the "added" side. The IIO driver updates are also coming through here, as they are tied to the staging iio drivers. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.21 (GNU/Linux) iEYEABECAAYFAlIlIrEACgkQMUfUDdst+ynjqgCgjMpPlRkU1yzDCj8CnfoLUI+v dIkAoLXD49aC8Km3f0LPUg/TgBA98MVx =FLQ/ -----END PGP SIGNATURE----- Merge tag 'staging-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging Pull staging tree merge from Greg KH: "Here's the bit staging tree pull request for 3.12-rc1. Lots of staging driver updates, and fixes. Lustre is finally enabled in the build, and lots of cleanup started happening in it. There's a new wireless driver in here, and 2 new TTY drivers, which cause the overall lines added/removed to be quite large on the "added" side. The IIO driver updates are also coming through here, as they are tied to the staging iio drivers" * tag 'staging-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (942 commits) staging: dwc2: make dwc2_core_params documentation more complete staging: dwc2: validate the value for phy_utmi_width staging: dwc2: interpret all hwcfg and related register at init time staging: dwc2: properly mask the GRXFSIZ register staging: dwc2: remove redundant register reads staging: dwc2: re-use hptxfsiz variable staging: dwc2: simplify debug output in dwc_hc_init staging: dwc2: add missing shift staging: dwc2: simplify register shift expressions staging: dwc2: only read the snpsid register once staging: dwc2: unshift non-bool register value constants staging: dwc2: fix off-by-one in check for max_packet_count parameter staging: dwc2: remove specific fifo size constants Staging:BCM:DDRInit.c:Renaming __FUNCTION__ staging: bcm: remove Version.h file. staging: rtl8188eu: off by one in rtw_set_802_11_add_wep() staging: r8188eu: copying one byte too much staging: rtl8188eu: || vs && typo staging: r8188eu: off by one bugs staging: crystalhd: Resolve sparse 'different base types' warnings. ...
This commit is contained in:
commit
751144271f
|
@ -351,6 +351,7 @@ Description:
|
|||
6kohm_to_gnd: connected to ground via a 6kOhm resistor,
|
||||
20kohm_to_gnd: connected to ground via a 20kOhm resistor,
|
||||
100kohm_to_gnd: connected to ground via an 100kOhm resistor,
|
||||
500kohm_to_gnd: connected to ground via a 500kOhm resistor,
|
||||
three_state: left floating.
|
||||
For a list of available output power down options read
|
||||
outX_powerdown_mode_available. If Y is not present the
|
||||
|
@ -792,3 +793,21 @@ Contact: linux-iio@vger.kernel.org
|
|||
Description:
|
||||
This attribute is used to read the amount of quadrature error
|
||||
present in the device at a given time.
|
||||
|
||||
What: /sys/.../iio:deviceX/in_accelX_power_mode
|
||||
KernelVersion: 3.11
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Specifies the chip power mode.
|
||||
low_noise: reduce noise level from ADC,
|
||||
low_power: enable low current consumption.
|
||||
For a list of available output power modes read
|
||||
in_accel_power_mode_available.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/store_eeprom
|
||||
KernelVersion: 3.4.0
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Writing '1' stores the current device configuration into
|
||||
on-chip EEPROM. After power-up or chip reset the device will
|
||||
automatically load the saved configuration.
|
||||
|
|
|
@ -18,14 +18,6 @@ Description:
|
|||
Reading returns either '1' or '0'. '1' means that the
|
||||
pllY is locked.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/store_eeprom
|
||||
KernelVersion: 3.4.0
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Writing '1' stores the current device configuration into
|
||||
on-chip EEPROM. After power-up or chip reset the device will
|
||||
automatically load the saved configuration.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/sync_dividers
|
||||
KernelVersion: 3.4.0
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
|
|
|
@ -18,4 +18,4 @@ Description:
|
|||
adjust the reference frequency accordingly.
|
||||
The value written has no effect until out_altvoltageY_frequency
|
||||
is updated. Consider to use out_altvoltageY_powerdown to power
|
||||
down the PLL and it's RFOut buffers during REFin changes.
|
||||
down the PLL and its RFOut buffers during REFin changes.
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
* AT91's Analog to Digital Converter (ADC)
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "atmel,at91sam9260-adc"
|
||||
- compatible: Should be "atmel,<chip>-adc"
|
||||
<chip> can be "at91sam9260", "at91sam9g45" or "at91sam9x5"
|
||||
- reg: Should contain ADC registers location and length
|
||||
- interrupts: Should contain the IRQ line for the ADC
|
||||
- atmel,adc-channel-base: Offset of the first channel data register
|
||||
- atmel,adc-channels-used: Bitmask of the channels muxed and enable for this
|
||||
device
|
||||
- atmel,adc-drdy-mask: Mask of the DRDY interruption in the ADC
|
||||
- atmel,adc-num-channels: Number of channels available in the ADC
|
||||
- atmel,adc-startup-time: Startup Time of the ADC in microseconds as
|
||||
defined in the datasheet
|
||||
- atmel,adc-status-register: Offset of the Interrupt Status Register
|
||||
- atmel,adc-trigger-register: Offset of the Trigger Register
|
||||
- atmel,adc-vref: Reference voltage in millivolts for the conversions
|
||||
- atmel,adc-res: List of resolution in bits supported by the ADC. List size
|
||||
must be two at least.
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
* Bosch BMA180 triaxial acceleration sensor
|
||||
|
||||
http://omapworld.com/BMA180_111_1002839.pdf
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be "bosch,bma180"
|
||||
- reg : the I2C address of the sensor
|
||||
|
||||
Optional properties:
|
||||
|
||||
- interrupt-parent : should be the phandle for the interrupt controller
|
||||
|
||||
- interrupts : interrupt mapping for GPIO IRQ, it should by configured with
|
||||
flags IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_EDGE_RISING
|
||||
|
||||
Example:
|
||||
|
||||
bma180@40 {
|
||||
compatible = "bosch,bma180";
|
||||
reg = <0x40>;
|
||||
interrupt-parent = <&gpio6>;
|
||||
interrupts = <18 (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_EDGE_RISING)>;
|
||||
};
|
|
@ -0,0 +1,18 @@
|
|||
* Nuvoton NAU7802 Analog to Digital Converter (ADC)
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "nuvoton,nau7802"
|
||||
- reg: Should contain the ADC I2C address
|
||||
|
||||
Optional properties:
|
||||
- nuvoton,vldo: Internal reference voltage in millivolts to be
|
||||
configured valid values are between 2400 mV and 4500 mV.
|
||||
- interrupts: IRQ line for the ADC. If not used the driver will use
|
||||
polling.
|
||||
|
||||
Example:
|
||||
adc2: nau7802@2a {
|
||||
compatible = "nuvoton,nau7802";
|
||||
reg = <0x2a>;
|
||||
nuvoton,vldo = <3000>;
|
||||
};
|
|
@ -0,0 +1,22 @@
|
|||
* Avago APDS9300 ambient light sensor
|
||||
|
||||
http://www.avagotech.com/docs/AV02-1077EN
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be "avago,apds9300"
|
||||
- reg : the I2C address of the sensor
|
||||
|
||||
Optional properties:
|
||||
|
||||
- interrupt-parent : should be the phandle for the interrupt controller
|
||||
- interrupts : interrupt mapping for GPIO IRQ
|
||||
|
||||
Example:
|
||||
|
||||
apds9300@39 {
|
||||
compatible = "avago,apds9300";
|
||||
reg = <0x39>;
|
||||
interrupt-parent = <&gpio2>;
|
||||
interrupts = <29 8>;
|
||||
};
|
|
@ -11,6 +11,7 @@ amcc Applied Micro Circuits Corporation (APM, formally AMCC)
|
|||
apm Applied Micro Circuits Corporation (APM)
|
||||
arm ARM Ltd.
|
||||
atmel Atmel Corporation
|
||||
avago Avago Technologies
|
||||
bosch Bosch Sensortec GmbH
|
||||
brcm Broadcom Corporation
|
||||
cavium Cavium, Inc.
|
||||
|
|
|
@ -237,6 +237,12 @@ MEM
|
|||
devm_kzalloc()
|
||||
devm_kfree()
|
||||
|
||||
IIO
|
||||
devm_iio_device_alloc()
|
||||
devm_iio_device_free()
|
||||
devm_iio_trigger_alloc()
|
||||
devm_iio_trigger_free()
|
||||
|
||||
IO region
|
||||
devm_request_region()
|
||||
devm_request_mem_region()
|
||||
|
|
|
@ -7890,11 +7890,11 @@ S: Maintained
|
|||
F: drivers/staging/nvec/
|
||||
|
||||
STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON)
|
||||
M: Andres Salomon <dilinger@queued.net>
|
||||
M: Chris Ball <cjb@laptop.org>
|
||||
M: Jens Frederich <jfrederich@gmail.com>
|
||||
M: Daniel Drake <dsd@laptop.org>
|
||||
M: Jon Nettleton <jon.nettleton@gmail.com>
|
||||
W: http://wiki.laptop.org/go/DCON
|
||||
S: Odd Fixes
|
||||
S: Maintained
|
||||
F: drivers/staging/olpc_dcon/
|
||||
|
||||
STAGING - OZMO DEVICES USB OVER WIFI DRIVER
|
||||
|
|
|
@ -28,9 +28,12 @@
|
|||
#define AT91_ADC_TRGSEL_EXTERNAL (6 << 1)
|
||||
#define AT91_ADC_LOWRES (1 << 4) /* Low Resolution */
|
||||
#define AT91_ADC_SLEEP (1 << 5) /* Sleep Mode */
|
||||
#define AT91_ADC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */
|
||||
#define AT91_ADC_PRESCAL_9260 (0x3f << 8) /* Prescalar Rate Selection */
|
||||
#define AT91_ADC_PRESCAL_9G45 (0xff << 8)
|
||||
#define AT91_ADC_PRESCAL_(x) ((x) << 8)
|
||||
#define AT91_ADC_STARTUP (0x1f << 16) /* Startup Up Time */
|
||||
#define AT91_ADC_STARTUP_9260 (0x1f << 16) /* Startup Up Time */
|
||||
#define AT91_ADC_STARTUP_9G45 (0x7f << 16)
|
||||
#define AT91_ADC_STARTUP_9X5 (0xf << 16)
|
||||
#define AT91_ADC_STARTUP_(x) ((x) << 16)
|
||||
#define AT91_ADC_SHTIM (0xf << 24) /* Sample & Hold Time */
|
||||
#define AT91_ADC_SHTIM_(x) ((x) << 24)
|
||||
|
@ -48,6 +51,9 @@
|
|||
#define AT91_ADC_ENDRX (1 << 18) /* End of RX Buffer */
|
||||
#define AT91_ADC_RXFUFF (1 << 19) /* RX Buffer Full */
|
||||
|
||||
#define AT91_ADC_SR_9X5 0x30 /* Status Register for 9x5 */
|
||||
#define AT91_ADC_SR_DRDY_9X5 (1 << 24) /* Data Ready */
|
||||
|
||||
#define AT91_ADC_LCDR 0x20 /* Last Converted Data Register */
|
||||
#define AT91_ADC_LDATA (0x3ff)
|
||||
|
||||
|
@ -58,4 +64,10 @@
|
|||
#define AT91_ADC_CHR(n) (0x30 + ((n) * 4)) /* Channel Data Register N */
|
||||
#define AT91_ADC_DATA (0x3ff)
|
||||
|
||||
#define AT91_ADC_CDR0_9X5 (0x50) /* Channel Data Register 0 for 9X5 */
|
||||
|
||||
#define AT91_ADC_TRGR_9260 AT91_ADC_MR
|
||||
#define AT91_ADC_TRGR_9G45 0x08
|
||||
#define AT91_ADC_TRGR_9X5 0xC0
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,15 +23,14 @@ if IIO_BUFFER
|
|||
config IIO_BUFFER_CB
|
||||
boolean "IIO callback buffer used for push in-kernel interfaces"
|
||||
help
|
||||
Should be selected by any drivers that do-inkernel push
|
||||
Should be selected by any drivers that do in-kernel push
|
||||
usage. That is, those where the data is pushed to the consumer.
|
||||
|
||||
config IIO_KFIFO_BUF
|
||||
select IIO_TRIGGER
|
||||
tristate "Industrial I/O buffering based on kfifo"
|
||||
help
|
||||
A simple fifo based on kfifo. Use this if you want a fifo
|
||||
rather than a ring buffer. Note that this currently provides
|
||||
A simple fifo based on kfifo. Note that this currently provides
|
||||
no buffer events so it is up to userspace to work out how
|
||||
often to read from the buffer.
|
||||
|
||||
|
@ -49,7 +48,7 @@ config IIO_TRIGGER
|
|||
help
|
||||
Provides IIO core support for triggers. Currently these
|
||||
are used to initialize capture of samples to push into
|
||||
ring buffers. The triggers are effectively a 'capture
|
||||
buffers. The triggers are effectively a 'capture
|
||||
data now' interrupt.
|
||||
|
||||
config IIO_CONSUMERS_PER_TRIGGER
|
||||
|
@ -74,5 +73,6 @@ if IIO_TRIGGER
|
|||
source "drivers/iio/trigger/Kconfig"
|
||||
endif #IIO_TRIGGER
|
||||
source "drivers/iio/pressure/Kconfig"
|
||||
source "drivers/iio/temperature/Kconfig"
|
||||
|
||||
endif # IIO
|
||||
|
|
|
@ -21,5 +21,6 @@ obj-y += frequency/
|
|||
obj-y += imu/
|
||||
obj-y += light/
|
||||
obj-y += magnetometer/
|
||||
obj-y += trigger/
|
||||
obj-y += pressure/
|
||||
obj-y += temperature/
|
||||
obj-y += trigger/
|
||||
|
|
|
@ -1,8 +1,22 @@
|
|||
#
|
||||
# Accelerometer drivers
|
||||
#
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
|
||||
menu "Accelerometers"
|
||||
|
||||
config BMA180
|
||||
tristate "Bosch BMA180 3-Axis Accelerometer Driver"
|
||||
depends on I2C
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
Say Y here if you want to build a driver for the Bosch BMA180
|
||||
triaxial acceleration sensor.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called bma180.
|
||||
|
||||
config HID_SENSOR_ACCEL_3D
|
||||
depends on HID_SENSOR_HUB
|
||||
select IIO_BUFFER
|
||||
|
@ -14,13 +28,6 @@ config HID_SENSOR_ACCEL_3D
|
|||
Say yes here to build support for the HID SENSOR
|
||||
accelerometers 3D.
|
||||
|
||||
config KXSD9
|
||||
tristate "Kionix KXSD9 Accelerometer Driver"
|
||||
depends on SPI
|
||||
help
|
||||
Say yes here to build support for the Kionix KXSD9 accelerometer.
|
||||
Currently this only supports the device via an SPI interface.
|
||||
|
||||
config IIO_ST_ACCEL_3AXIS
|
||||
tristate "STMicroelectronics accelerometers 3-Axis Driver"
|
||||
depends on (I2C || SPI_MASTER) && SYSFS
|
||||
|
@ -33,8 +40,8 @@ config IIO_ST_ACCEL_3AXIS
|
|||
LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,
|
||||
LIS331DLH, LSM303DL, LSM303DLM, LSM330.
|
||||
|
||||
This driver can also be built as a module. If so, will be created
|
||||
these modules:
|
||||
This driver can also be built as a module. If so, these modules
|
||||
will be created:
|
||||
- st_accel (core functions for the driver [it is mandatory]);
|
||||
- st_accel_i2c (necessary for the I2C devices [optional*]);
|
||||
- st_accel_spi (necessary for the SPI devices [optional*]);
|
||||
|
@ -51,4 +58,11 @@ config IIO_ST_ACCEL_SPI_3AXIS
|
|||
depends on IIO_ST_ACCEL_3AXIS
|
||||
depends on IIO_ST_SENSORS_SPI
|
||||
|
||||
config KXSD9
|
||||
tristate "Kionix KXSD9 Accelerometer Driver"
|
||||
depends on SPI
|
||||
help
|
||||
Say yes here to build support for the Kionix KXSD9 accelerometer.
|
||||
Currently this only supports the device via an SPI interface.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
# Makefile for industrial I/O accelerometer drivers
|
||||
#
|
||||
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
obj-$(CONFIG_BMA180) += bma180.o
|
||||
obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
|
||||
obj-$(CONFIG_KXSD9) += kxsd9.o
|
||||
|
||||
obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o
|
||||
st_accel-y := st_accel_core.o
|
||||
|
@ -10,5 +13,3 @@ st_accel-$(CONFIG_IIO_BUFFER) += st_accel_buffer.o
|
|||
|
||||
obj-$(CONFIG_IIO_ST_ACCEL_I2C_3AXIS) += st_accel_i2c.o
|
||||
obj-$(CONFIG_IIO_ST_ACCEL_SPI_3AXIS) += st_accel_spi.o
|
||||
|
||||
obj-$(CONFIG_KXSD9) += kxsd9.o
|
||||
|
|
|
@ -0,0 +1,676 @@
|
|||
/*
|
||||
* bma180.c - IIO driver for Bosch BMA180 triaxial acceleration sensor
|
||||
*
|
||||
* Copyright 2013 Oleksandr Kravchenko <x0199363@ti.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
|
||||
#define BMA180_DRV_NAME "bma180"
|
||||
#define BMA180_IRQ_NAME "bma180_event"
|
||||
|
||||
/* Register set */
|
||||
#define BMA180_CHIP_ID 0x00 /* Need to distinguish BMA180 from other */
|
||||
#define BMA180_ACC_X_LSB 0x02 /* First of 6 registers of accel data */
|
||||
#define BMA180_CTRL_REG0 0x0d
|
||||
#define BMA180_RESET 0x10
|
||||
#define BMA180_BW_TCS 0x20
|
||||
#define BMA180_CTRL_REG3 0x21
|
||||
#define BMA180_TCO_Z 0x30
|
||||
#define BMA180_OFFSET_LSB1 0x35
|
||||
|
||||
/* BMA180_CTRL_REG0 bits */
|
||||
#define BMA180_DIS_WAKE_UP BIT(0) /* Disable wake up mode */
|
||||
#define BMA180_SLEEP BIT(1) /* 1 - chip will sleep */
|
||||
#define BMA180_EE_W BIT(4) /* Unlock writing to addr from 0x20 */
|
||||
#define BMA180_RESET_INT BIT(6) /* Reset pending interrupts */
|
||||
|
||||
/* BMA180_CTRL_REG3 bits */
|
||||
#define BMA180_NEW_DATA_INT BIT(1) /* Intr every new accel data is ready */
|
||||
|
||||
/* BMA180_OFFSET_LSB1 skipping mode bit */
|
||||
#define BMA180_SMP_SKIP BIT(0)
|
||||
|
||||
/* Bit masks for registers bit fields */
|
||||
#define BMA180_RANGE 0x0e /* Range of measured accel values*/
|
||||
#define BMA180_BW 0xf0 /* Accel bandwidth */
|
||||
#define BMA180_MODE_CONFIG 0x03 /* Config operation modes */
|
||||
|
||||
/* We have to write this value in reset register to do soft reset */
|
||||
#define BMA180_RESET_VAL 0xb6
|
||||
|
||||
#define BMA_180_ID_REG_VAL 0x03
|
||||
|
||||
/* Chip power modes */
|
||||
#define BMA180_LOW_NOISE 0x00
|
||||
#define BMA180_LOW_POWER 0x03
|
||||
|
||||
#define BMA180_LOW_NOISE_STR "low_noise"
|
||||
#define BMA180_LOW_POWER_STR "low_power"
|
||||
|
||||
/* Defaults values */
|
||||
#define BMA180_DEF_PMODE 0
|
||||
#define BMA180_DEF_BW 20
|
||||
#define BMA180_DEF_SCALE 250
|
||||
|
||||
/* Available values for sysfs */
|
||||
#define BMA180_FLP_FREQ_AVAILABLE \
|
||||
"10 20 40 75 150 300"
|
||||
#define BMA180_SCALE_AVAILABLE \
|
||||
"0.000130 0.000190 0.000250 0.000380 0.000500 0.000990 0.001980"
|
||||
|
||||
struct bma180_data {
|
||||
struct i2c_client *client;
|
||||
struct iio_trigger *trig;
|
||||
struct mutex mutex;
|
||||
int sleep_state;
|
||||
int scale;
|
||||
int bw;
|
||||
int pmode;
|
||||
char *buff;
|
||||
};
|
||||
|
||||
enum bma180_axis {
|
||||
AXIS_X,
|
||||
AXIS_Y,
|
||||
AXIS_Z,
|
||||
};
|
||||
|
||||
static int bw_table[] = { 10, 20, 40, 75, 150, 300 }; /* Hz */
|
||||
static int scale_table[] = { 130, 190, 250, 380, 500, 990, 1980 };
|
||||
|
||||
static int bma180_get_acc_reg(struct bma180_data *data, enum bma180_axis axis)
|
||||
{
|
||||
u8 reg = BMA180_ACC_X_LSB + axis * 2;
|
||||
int ret;
|
||||
|
||||
if (data->sleep_state)
|
||||
return -EBUSY;
|
||||
|
||||
ret = i2c_smbus_read_word_data(data->client, reg);
|
||||
if (ret < 0)
|
||||
dev_err(&data->client->dev,
|
||||
"failed to read accel_%c registers\n", 'x' + axis);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bma180_set_bits(struct bma180_data *data, u8 reg, u8 mask, u8 val)
|
||||
{
|
||||
int ret = i2c_smbus_read_byte_data(data->client, reg);
|
||||
u8 reg_val = (ret & ~mask) | (val << (ffs(mask) - 1));
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return i2c_smbus_write_byte_data(data->client, reg, reg_val);
|
||||
}
|
||||
|
||||
static int bma180_reset_intr(struct bma180_data *data)
|
||||
{
|
||||
int ret = bma180_set_bits(data, BMA180_CTRL_REG0, BMA180_RESET_INT, 1);
|
||||
|
||||
if (ret)
|
||||
dev_err(&data->client->dev, "failed to reset interrupt\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bma180_set_new_data_intr_state(struct bma180_data *data, int state)
|
||||
{
|
||||
u8 reg_val = state ? BMA180_NEW_DATA_INT : 0x00;
|
||||
int ret = i2c_smbus_write_byte_data(data->client, BMA180_CTRL_REG3,
|
||||
reg_val);
|
||||
|
||||
if (ret)
|
||||
goto err;
|
||||
ret = bma180_reset_intr(data);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
dev_err(&data->client->dev,
|
||||
"failed to set new data interrupt state %d\n", state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bma180_set_sleep_state(struct bma180_data *data, int state)
|
||||
{
|
||||
int ret = bma180_set_bits(data, BMA180_CTRL_REG0, BMA180_SLEEP, state);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev,
|
||||
"failed to set sleep state %d\n", state);
|
||||
return ret;
|
||||
}
|
||||
data->sleep_state = state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bma180_set_ee_writing_state(struct bma180_data *data, int state)
|
||||
{
|
||||
int ret = bma180_set_bits(data, BMA180_CTRL_REG0, BMA180_EE_W, state);
|
||||
|
||||
if (ret)
|
||||
dev_err(&data->client->dev,
|
||||
"failed to set ee writing state %d\n", state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bma180_set_bw(struct bma180_data *data, int val)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
if (data->sleep_state)
|
||||
return -EBUSY;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bw_table); ++i) {
|
||||
if (bw_table[i] == val) {
|
||||
ret = bma180_set_bits(data,
|
||||
BMA180_BW_TCS, BMA180_BW, i);
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev,
|
||||
"failed to set bandwidth\n");
|
||||
return ret;
|
||||
}
|
||||
data->bw = val;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int bma180_set_scale(struct bma180_data *data, int val)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
if (data->sleep_state)
|
||||
return -EBUSY;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(scale_table); ++i)
|
||||
if (scale_table[i] == val) {
|
||||
ret = bma180_set_bits(data,
|
||||
BMA180_OFFSET_LSB1, BMA180_RANGE, i);
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev,
|
||||
"failed to set scale\n");
|
||||
return ret;
|
||||
}
|
||||
data->scale = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int bma180_set_pmode(struct bma180_data *data, int mode)
|
||||
{
|
||||
u8 reg_val = mode ? BMA180_LOW_POWER : BMA180_LOW_NOISE;
|
||||
int ret = bma180_set_bits(data, BMA180_TCO_Z, BMA180_MODE_CONFIG,
|
||||
reg_val);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev, "failed to set power mode\n");
|
||||
return ret;
|
||||
}
|
||||
data->pmode = mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bma180_soft_reset(struct bma180_data *data)
|
||||
{
|
||||
int ret = i2c_smbus_write_byte_data(data->client,
|
||||
BMA180_RESET, BMA180_RESET_VAL);
|
||||
|
||||
if (ret)
|
||||
dev_err(&data->client->dev, "failed to reset the chip\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bma180_chip_init(struct bma180_data *data)
|
||||
{
|
||||
/* Try to read chip_id register. It must return 0x03. */
|
||||
int ret = i2c_smbus_read_byte_data(data->client, BMA180_CHIP_ID);
|
||||
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
if (ret != BMA_180_ID_REG_VAL) {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = bma180_soft_reset(data);
|
||||
if (ret)
|
||||
goto err;
|
||||
/*
|
||||
* No serial transaction should occur within minimum 10 us
|
||||
* after soft_reset command
|
||||
*/
|
||||
msleep(20);
|
||||
|
||||
ret = bma180_set_bits(data, BMA180_CTRL_REG0, BMA180_DIS_WAKE_UP, 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
ret = bma180_set_ee_writing_state(data, 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
ret = bma180_set_new_data_intr_state(data, 0);
|
||||
if (ret)
|
||||
goto err;
|
||||
ret = bma180_set_bits(data, BMA180_OFFSET_LSB1, BMA180_SMP_SKIP, 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
ret = bma180_set_pmode(data, BMA180_DEF_PMODE);
|
||||
if (ret)
|
||||
goto err;
|
||||
ret = bma180_set_bw(data, BMA180_DEF_BW);
|
||||
if (ret)
|
||||
goto err;
|
||||
ret = bma180_set_scale(data, BMA180_DEF_SCALE);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
dev_err(&data->client->dev, "failed to init the chip\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bma180_chip_disable(struct bma180_data *data)
|
||||
{
|
||||
if (bma180_set_new_data_intr_state(data, 0))
|
||||
goto err;
|
||||
if (bma180_set_ee_writing_state(data, 0))
|
||||
goto err;
|
||||
if (bma180_set_sleep_state(data, 1))
|
||||
goto err;
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
dev_err(&data->client->dev, "failed to disable the chip\n");
|
||||
}
|
||||
|
||||
static IIO_CONST_ATTR(in_accel_filter_low_pass_3db_frequency_available,
|
||||
BMA180_FLP_FREQ_AVAILABLE);
|
||||
static IIO_CONST_ATTR(in_accel_scale_available, BMA180_SCALE_AVAILABLE);
|
||||
|
||||
static struct attribute *bma180_attributes[] = {
|
||||
&iio_const_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr,
|
||||
&iio_const_attr_in_accel_scale_available.dev_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group bma180_attrs_group = {
|
||||
.attrs = bma180_attributes,
|
||||
};
|
||||
|
||||
static int bma180_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan, int *val, int *val2,
|
||||
long mask)
|
||||
{
|
||||
struct bma180_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
mutex_lock(&data->mutex);
|
||||
if (iio_buffer_enabled(indio_dev))
|
||||
ret = -EBUSY;
|
||||
else
|
||||
ret = bma180_get_acc_reg(data, chan->scan_index);
|
||||
mutex_unlock(&data->mutex);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = (s16)ret >> chan->scan_type.shift;
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
||||
*val = data->bw;
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*val = 0;
|
||||
*val2 = data->scale;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int bma180_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan, int val, int val2, long mask)
|
||||
{
|
||||
struct bma180_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
if (val)
|
||||
return -EINVAL;
|
||||
mutex_lock(&data->mutex);
|
||||
ret = bma180_set_scale(data, val2);
|
||||
mutex_unlock(&data->mutex);
|
||||
return ret;
|
||||
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
||||
mutex_lock(&data->mutex);
|
||||
ret = bma180_set_bw(data, val);
|
||||
mutex_unlock(&data->mutex);
|
||||
return ret;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int bma180_update_scan_mode(struct iio_dev *indio_dev,
|
||||
const unsigned long *scan_mask)
|
||||
{
|
||||
struct bma180_data *data = iio_priv(indio_dev);
|
||||
|
||||
if (data->buff)
|
||||
devm_kfree(&indio_dev->dev, data->buff);
|
||||
data->buff = devm_kzalloc(&indio_dev->dev,
|
||||
indio_dev->scan_bytes, GFP_KERNEL);
|
||||
if (!data->buff)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iio_info bma180_info = {
|
||||
.attrs = &bma180_attrs_group,
|
||||
.read_raw = bma180_read_raw,
|
||||
.write_raw = bma180_write_raw,
|
||||
.update_scan_mode = bma180_update_scan_mode,
|
||||
.driver_module = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const char * const bma180_power_modes[] = {
|
||||
BMA180_LOW_NOISE_STR,
|
||||
BMA180_LOW_POWER_STR,
|
||||
};
|
||||
|
||||
static int bma180_get_power_mode(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan)
|
||||
{
|
||||
struct bma180_data *data = iio_priv(indio_dev);
|
||||
|
||||
return data->pmode;
|
||||
}
|
||||
|
||||
static int bma180_set_power_mode(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan, unsigned int mode)
|
||||
{
|
||||
struct bma180_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
ret = bma180_set_pmode(data, mode);
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct iio_enum bma180_power_mode_enum = {
|
||||
.items = bma180_power_modes,
|
||||
.num_items = ARRAY_SIZE(bma180_power_modes),
|
||||
.get = bma180_get_power_mode,
|
||||
.set = bma180_set_power_mode,
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec_ext_info bma180_ext_info[] = {
|
||||
IIO_ENUM("power_mode", true, &bma180_power_mode_enum),
|
||||
IIO_ENUM_AVAILABLE("power_mode", &bma180_power_mode_enum),
|
||||
{ },
|
||||
};
|
||||
|
||||
#define BMA180_CHANNEL(_index) { \
|
||||
.type = IIO_ACCEL, \
|
||||
.indexed = 1, \
|
||||
.channel = (_index), \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
||||
.scan_index = (_index), \
|
||||
.scan_type = IIO_ST('s', 14, 16, 2), \
|
||||
.ext_info = bma180_ext_info, \
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec bma180_channels[] = {
|
||||
BMA180_CHANNEL(AXIS_X),
|
||||
BMA180_CHANNEL(AXIS_Y),
|
||||
BMA180_CHANNEL(AXIS_Z),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(4),
|
||||
};
|
||||
|
||||
static irqreturn_t bma180_trigger_handler(int irq, void *p)
|
||||
{
|
||||
struct iio_poll_func *pf = p;
|
||||
struct iio_dev *indio_dev = pf->indio_dev;
|
||||
struct bma180_data *data = iio_priv(indio_dev);
|
||||
int bit, ret, i = 0;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
if (indio_dev->scan_timestamp) {
|
||||
ret = indio_dev->scan_bytes / sizeof(s64) - 1;
|
||||
((s64 *)data->buff)[ret] = iio_get_time_ns();
|
||||
}
|
||||
|
||||
for_each_set_bit(bit, indio_dev->buffer->scan_mask,
|
||||
indio_dev->masklength) {
|
||||
ret = bma180_get_acc_reg(data, bit);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&data->mutex);
|
||||
goto err;
|
||||
}
|
||||
((s16 *)data->buff)[i++] = ret;
|
||||
}
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
iio_push_to_buffers(indio_dev, (u8 *)data->buff);
|
||||
err:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int bma180_data_rdy_trigger_set_state(struct iio_trigger *trig,
|
||||
bool state)
|
||||
{
|
||||
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
|
||||
struct bma180_data *data = iio_priv(indio_dev);
|
||||
|
||||
return bma180_set_new_data_intr_state(data, state);
|
||||
}
|
||||
|
||||
static int bma180_trig_try_reen(struct iio_trigger *trig)
|
||||
{
|
||||
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
|
||||
struct bma180_data *data = iio_priv(indio_dev);
|
||||
|
||||
return bma180_reset_intr(data);
|
||||
}
|
||||
|
||||
static const struct iio_trigger_ops bma180_trigger_ops = {
|
||||
.set_trigger_state = bma180_data_rdy_trigger_set_state,
|
||||
.try_reenable = bma180_trig_try_reen,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int bma180_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct bma180_data *data;
|
||||
struct iio_dev *indio_dev;
|
||||
struct iio_trigger *trig;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
data = iio_priv(indio_dev);
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
data->client = client;
|
||||
|
||||
ret = bma180_chip_init(data);
|
||||
if (ret < 0)
|
||||
goto err_chip_disable;
|
||||
|
||||
mutex_init(&data->mutex);
|
||||
|
||||
indio_dev->dev.parent = &client->dev;
|
||||
indio_dev->channels = bma180_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(bma180_channels);
|
||||
indio_dev->name = BMA180_DRV_NAME;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->info = &bma180_info;
|
||||
|
||||
trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);
|
||||
if (!trig) {
|
||||
ret = -ENOMEM;
|
||||
goto err_chip_disable;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&client->dev, client->irq,
|
||||
iio_trigger_generic_data_rdy_poll,
|
||||
IRQF_TRIGGER_RISING, BMA180_IRQ_NAME, trig);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "unable to request IRQ\n");
|
||||
goto err_trigger_free;
|
||||
}
|
||||
|
||||
trig->dev.parent = &client->dev;
|
||||
trig->ops = &bma180_trigger_ops;
|
||||
iio_trigger_set_drvdata(trig, indio_dev);
|
||||
data->trig = trig;
|
||||
indio_dev->trig = trig;
|
||||
|
||||
ret = iio_trigger_register(trig);
|
||||
if (ret)
|
||||
goto err_trigger_free;
|
||||
|
||||
ret = iio_triggered_buffer_setup(indio_dev, NULL,
|
||||
bma180_trigger_handler, NULL);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "unable to setup iio triggered buffer\n");
|
||||
goto err_trigger_unregister;
|
||||
}
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "unable to register iio device\n");
|
||||
goto err_buffer_cleanup;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_buffer_cleanup:
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
err_trigger_unregister:
|
||||
iio_trigger_unregister(trig);
|
||||
err_trigger_free:
|
||||
iio_trigger_free(trig);
|
||||
err_chip_disable:
|
||||
bma180_chip_disable(data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bma180_remove(struct i2c_client *client)
|
||||
{
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
||||
struct bma180_data *data = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
iio_trigger_unregister(data->trig);
|
||||
iio_trigger_free(data->trig);
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
bma180_chip_disable(data);
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int bma180_suspend(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct bma180_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
ret = bma180_set_sleep_state(data, 1);
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bma180_resume(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct bma180_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
ret = bma180_set_sleep_state(data, 0);
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume);
|
||||
#define BMA180_PM_OPS (&bma180_pm_ops)
|
||||
#else
|
||||
#define BMA180_PM_OPS NULL
|
||||
#endif
|
||||
|
||||
static struct i2c_device_id bma180_id[] = {
|
||||
{ BMA180_DRV_NAME, 0 },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, bma180_id);
|
||||
|
||||
static struct i2c_driver bma180_driver = {
|
||||
.driver = {
|
||||
.name = BMA180_DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = BMA180_PM_OPS,
|
||||
},
|
||||
.probe = bma180_probe,
|
||||
.remove = bma180_remove,
|
||||
.id_table = bma180_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(bma180_driver);
|
||||
|
||||
MODULE_AUTHOR("Kravchenko Oleksandr <x0199363@ti.com>");
|
||||
MODULE_AUTHOR("Texas Instruments, Inc.");
|
||||
MODULE_DESCRIPTION("Bosch BMA180 triaxial acceleration sensor");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -30,10 +30,6 @@
|
|||
#include <linux/iio/triggered_buffer.h>
|
||||
#include "../common/hid-sensors/hid-sensor-trigger.h"
|
||||
|
||||
/*Format: HID-SENSOR-usage_id_in_hex*/
|
||||
/*Usage ID from spec for Accelerometer-3D: 0x200073*/
|
||||
#define DRIVER_NAME "HID-SENSOR-200073"
|
||||
|
||||
enum accel_3d_channel {
|
||||
CHANNEL_SCAN_INDEX_X,
|
||||
CHANNEL_SCAN_INDEX_Y,
|
||||
|
@ -179,18 +175,10 @@ static int accel_3d_write_raw(struct iio_dev *indio_dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int accel_3d_write_raw_get_fmt(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
long mask)
|
||||
{
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
}
|
||||
|
||||
static const struct iio_info accel_3d_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = &accel_3d_read_raw,
|
||||
.write_raw = &accel_3d_write_raw,
|
||||
.write_raw_get_fmt = &accel_3d_write_raw_get_fmt,
|
||||
};
|
||||
|
||||
/* Function to push data to buffer */
|
||||
|
@ -286,11 +274,11 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
|
|||
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
|
||||
struct iio_chan_spec *channels;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(struct accel_3d_state));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev,
|
||||
sizeof(struct accel_3d_state));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
|
||||
accel_state = iio_priv(indio_dev);
|
||||
|
@ -302,15 +290,14 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
|
|||
&accel_state->common_attributes);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to setup common attributes\n");
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
}
|
||||
|
||||
channels = kmemdup(accel_3d_channels, sizeof(accel_3d_channels),
|
||||
GFP_KERNEL);
|
||||
if (!channels) {
|
||||
ret = -ENOMEM;
|
||||
dev_err(&pdev->dev, "failed to duplicate channels\n");
|
||||
goto error_free_dev;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = accel_3d_parse_report(pdev, hsdev, channels,
|
||||
|
@ -367,9 +354,6 @@ error_unreg_buffer_funcs:
|
|||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
error_free_dev_mem:
|
||||
kfree(indio_dev->channels);
|
||||
error_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -384,14 +368,23 @@ static int hid_accel_3d_remove(struct platform_device *pdev)
|
|||
hid_sensor_remove_trigger(indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
kfree(indio_dev->channels);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_device_id hid_accel_3d_ids[] = {
|
||||
{
|
||||
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
|
||||
.name = "HID-SENSOR-200073",
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, hid_accel_3d_ids);
|
||||
|
||||
static struct platform_driver hid_accel_3d_platform_driver = {
|
||||
.id_table = hid_accel_3d_ids,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.name = KBUILD_MODNAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = hid_accel_3d_probe,
|
||||
|
|
|
@ -224,11 +224,10 @@ static int kxsd9_probe(struct spi_device *spi)
|
|||
struct kxsd9_state *st;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
spi_set_drvdata(spi, indio_dev);
|
||||
|
||||
|
@ -247,20 +246,14 @@ static int kxsd9_probe(struct spi_device *spi)
|
|||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret)
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
|
||||
error_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kxsd9_remove(struct spi_device *spi)
|
||||
{
|
||||
iio_device_unregister(spi_get_drvdata(spi));
|
||||
iio_device_free(spi_get_drvdata(spi));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,16 @@
|
|||
#define LSM303DLM_ACCEL_DEV_NAME "lsm303dlm_accel"
|
||||
#define LSM330_ACCEL_DEV_NAME "lsm330_accel"
|
||||
|
||||
int st_accel_common_probe(struct iio_dev *indio_dev);
|
||||
/**
|
||||
* struct st_sensors_platform_data - default accel platform data
|
||||
* @drdy_int_pin: default accel DRDY is available on INT1 pin.
|
||||
*/
|
||||
static const struct st_sensors_platform_data default_accel_pdata = {
|
||||
.drdy_int_pin = 1,
|
||||
};
|
||||
|
||||
int st_accel_common_probe(struct iio_dev *indio_dev,
|
||||
struct st_sensors_platform_data *pdata);
|
||||
void st_accel_common_remove(struct iio_dev *indio_dev);
|
||||
|
||||
#ifdef CONFIG_IIO_BUFFER
|
||||
|
|
|
@ -65,7 +65,8 @@
|
|||
#define ST_ACCEL_1_BDU_ADDR 0x23
|
||||
#define ST_ACCEL_1_BDU_MASK 0x80
|
||||
#define ST_ACCEL_1_DRDY_IRQ_ADDR 0x22
|
||||
#define ST_ACCEL_1_DRDY_IRQ_MASK 0x10
|
||||
#define ST_ACCEL_1_DRDY_IRQ_INT1_MASK 0x10
|
||||
#define ST_ACCEL_1_DRDY_IRQ_INT2_MASK 0x08
|
||||
#define ST_ACCEL_1_MULTIREAD_BIT true
|
||||
|
||||
/* CUSTOM VALUES FOR SENSOR 2 */
|
||||
|
@ -89,7 +90,8 @@
|
|||
#define ST_ACCEL_2_BDU_ADDR 0x23
|
||||
#define ST_ACCEL_2_BDU_MASK 0x80
|
||||
#define ST_ACCEL_2_DRDY_IRQ_ADDR 0x22
|
||||
#define ST_ACCEL_2_DRDY_IRQ_MASK 0x02
|
||||
#define ST_ACCEL_2_DRDY_IRQ_INT1_MASK 0x02
|
||||
#define ST_ACCEL_2_DRDY_IRQ_INT2_MASK 0x10
|
||||
#define ST_ACCEL_2_MULTIREAD_BIT true
|
||||
|
||||
/* CUSTOM VALUES FOR SENSOR 3 */
|
||||
|
@ -121,7 +123,8 @@
|
|||
#define ST_ACCEL_3_BDU_ADDR 0x20
|
||||
#define ST_ACCEL_3_BDU_MASK 0x08
|
||||
#define ST_ACCEL_3_DRDY_IRQ_ADDR 0x23
|
||||
#define ST_ACCEL_3_DRDY_IRQ_MASK 0x80
|
||||
#define ST_ACCEL_3_DRDY_IRQ_INT1_MASK 0x80
|
||||
#define ST_ACCEL_3_DRDY_IRQ_INT2_MASK 0x00
|
||||
#define ST_ACCEL_3_IG1_EN_ADDR 0x23
|
||||
#define ST_ACCEL_3_IG1_EN_MASK 0x08
|
||||
#define ST_ACCEL_3_MULTIREAD_BIT false
|
||||
|
@ -224,7 +227,8 @@ static const struct st_sensors st_accel_sensors[] = {
|
|||
},
|
||||
.drdy_irq = {
|
||||
.addr = ST_ACCEL_1_DRDY_IRQ_ADDR,
|
||||
.mask = ST_ACCEL_1_DRDY_IRQ_MASK,
|
||||
.mask_int1 = ST_ACCEL_1_DRDY_IRQ_INT1_MASK,
|
||||
.mask_int2 = ST_ACCEL_1_DRDY_IRQ_INT2_MASK,
|
||||
},
|
||||
.multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT,
|
||||
.bootime = 2,
|
||||
|
@ -285,7 +289,8 @@ static const struct st_sensors st_accel_sensors[] = {
|
|||
},
|
||||
.drdy_irq = {
|
||||
.addr = ST_ACCEL_2_DRDY_IRQ_ADDR,
|
||||
.mask = ST_ACCEL_2_DRDY_IRQ_MASK,
|
||||
.mask_int1 = ST_ACCEL_2_DRDY_IRQ_INT1_MASK,
|
||||
.mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK,
|
||||
},
|
||||
.multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT,
|
||||
.bootime = 2,
|
||||
|
@ -358,7 +363,8 @@ static const struct st_sensors st_accel_sensors[] = {
|
|||
},
|
||||
.drdy_irq = {
|
||||
.addr = ST_ACCEL_3_DRDY_IRQ_ADDR,
|
||||
.mask = ST_ACCEL_3_DRDY_IRQ_MASK,
|
||||
.mask_int1 = ST_ACCEL_3_DRDY_IRQ_INT1_MASK,
|
||||
.mask_int2 = ST_ACCEL_3_DRDY_IRQ_INT2_MASK,
|
||||
.ig1 = {
|
||||
.en_addr = ST_ACCEL_3_IG1_EN_ADDR,
|
||||
.en_mask = ST_ACCEL_3_IG1_EN_MASK,
|
||||
|
@ -443,7 +449,8 @@ static const struct iio_trigger_ops st_accel_trigger_ops = {
|
|||
#define ST_ACCEL_TRIGGER_OPS NULL
|
||||
#endif
|
||||
|
||||
int st_accel_common_probe(struct iio_dev *indio_dev)
|
||||
int st_accel_common_probe(struct iio_dev *indio_dev,
|
||||
struct st_sensors_platform_data *plat_data)
|
||||
{
|
||||
int err;
|
||||
struct st_sensor_data *adata = iio_priv(indio_dev);
|
||||
|
@ -465,7 +472,11 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
|
|||
&adata->sensor->fs.fs_avl[0];
|
||||
adata->odr = adata->sensor->odr.odr_avl[0].hz;
|
||||
|
||||
err = st_sensors_init_sensor(indio_dev);
|
||||
if (!plat_data)
|
||||
plat_data =
|
||||
(struct st_sensors_platform_data *)&default_accel_pdata;
|
||||
|
||||
err = st_sensors_init_sensor(indio_dev, plat_data);
|
||||
if (err < 0)
|
||||
goto st_accel_common_probe_error;
|
||||
|
||||
|
@ -506,7 +517,6 @@ void st_accel_common_remove(struct iio_dev *indio_dev)
|
|||
st_sensors_deallocate_trigger(indio_dev);
|
||||
st_accel_deallocate_ring(indio_dev);
|
||||
}
|
||||
iio_device_free(indio_dev);
|
||||
}
|
||||
EXPORT_SYMBOL(st_accel_common_remove);
|
||||
|
||||
|
|
|
@ -25,27 +25,20 @@ static int st_accel_i2c_probe(struct i2c_client *client,
|
|||
struct st_sensor_data *adata;
|
||||
int err;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*adata));
|
||||
if (indio_dev == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto iio_device_alloc_error;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*adata));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
adata = iio_priv(indio_dev);
|
||||
adata->dev = &client->dev;
|
||||
|
||||
st_sensors_i2c_configure(indio_dev, client, adata);
|
||||
|
||||
err = st_accel_common_probe(indio_dev);
|
||||
err = st_accel_common_probe(indio_dev, client->dev.platform_data);
|
||||
if (err < 0)
|
||||
goto st_accel_common_probe_error;
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
|
||||
st_accel_common_probe_error:
|
||||
iio_device_free(indio_dev);
|
||||
iio_device_alloc_error:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int st_accel_i2c_remove(struct i2c_client *client)
|
||||
|
|
|
@ -24,27 +24,20 @@ static int st_accel_spi_probe(struct spi_device *spi)
|
|||
struct st_sensor_data *adata;
|
||||
int err;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*adata));
|
||||
if (indio_dev == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto iio_device_alloc_error;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adata));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
adata = iio_priv(indio_dev);
|
||||
adata->dev = &spi->dev;
|
||||
|
||||
st_sensors_spi_configure(indio_dev, spi, adata);
|
||||
|
||||
err = st_accel_common_probe(indio_dev);
|
||||
err = st_accel_common_probe(indio_dev, spi->dev.platform_data);
|
||||
if (err < 0)
|
||||
goto st_accel_common_probe_error;
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
|
||||
st_accel_common_probe_error:
|
||||
iio_device_free(indio_dev);
|
||||
iio_device_alloc_error:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int st_accel_spi_remove(struct spi_device *spi)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# ADC drivers
|
||||
#
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
|
||||
menu "Analog to digital converters"
|
||||
|
||||
config AD_SIGMA_DELTA
|
||||
|
@ -30,17 +32,20 @@ config AD7298
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad7298.
|
||||
|
||||
config AD7923
|
||||
tristate "Analog Devices AD7923 and similar ADCs driver"
|
||||
config AD7476
|
||||
tristate "Analog Devices AD7476 and similar 1-channel ADCs driver"
|
||||
depends on SPI
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
Say yes here to build support for Analog Devices
|
||||
AD7904, AD7914, AD7923, AD7924 4 Channel ADCs.
|
||||
Say yes here to build support for Analog Devices AD7273, AD7274, AD7276,
|
||||
AD7277, AD7278, AD7475, AD7476, AD7477, AD7478, AD7466, AD7467, AD7468,
|
||||
AD7495, AD7910, AD7920, AD7920 SPI analog to digital converters (ADC).
|
||||
|
||||
If unsure, say N (but it's safe to say "Y").
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad7923.
|
||||
module will be called ad7476.
|
||||
|
||||
config AD7791
|
||||
tristate "Analog Devices AD7791 ADC driver"
|
||||
|
@ -66,21 +71,6 @@ config AD7793
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called AD7793.
|
||||
|
||||
config AD7476
|
||||
tristate "Analog Devices AD7476 and similar 1-channel ADCs driver"
|
||||
depends on SPI
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
Say yes here to build support for Analog Devices AD7273, AD7274, AD7276,
|
||||
AD7277, AD7278, AD7475, AD7476, AD7477, AD7478, AD7466, AD7467, AD7468,
|
||||
AD7495, AD7910, AD7920, AD7920 SPI analog to digital converters (ADC).
|
||||
|
||||
If unsure, say N (but it's safe to say "Y").
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad7476.
|
||||
|
||||
config AD7887
|
||||
tristate "Analog Devices AD7887 ADC driver"
|
||||
depends on SPI
|
||||
|
@ -94,6 +84,18 @@ config AD7887
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad7887.
|
||||
|
||||
config AD7923
|
||||
tristate "Analog Devices AD7923 and similar ADCs driver"
|
||||
depends on SPI
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
Say yes here to build support for Analog Devices
|
||||
AD7904, AD7914, AD7923, AD7924 4 Channel ADCs.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad7923.
|
||||
|
||||
config AT91_ADC
|
||||
tristate "Atmel AT91 ADC"
|
||||
depends on ARCH_AT91
|
||||
|
@ -143,6 +145,15 @@ config MCP320X
|
|||
This driver can also be built as a module. If so, the module will be
|
||||
called mcp320x.
|
||||
|
||||
config NAU7802
|
||||
tristate "Nuvoton NAU7802 ADC driver"
|
||||
depends on I2C
|
||||
help
|
||||
Say yes here to build support for Nuvoton NAU7802 ADC.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called nau7802.
|
||||
|
||||
config TI_ADC081C
|
||||
tristate "Texas Instruments ADC081C021/027"
|
||||
depends on I2C
|
||||
|
@ -154,12 +165,26 @@ config TI_ADC081C
|
|||
called ti-adc081c.
|
||||
|
||||
config TI_AM335X_ADC
|
||||
tristate "TI's ADC driver"
|
||||
tristate "TI's AM335X ADC driver"
|
||||
depends on MFD_TI_AM335X_TSCADC
|
||||
help
|
||||
Say yes here to build support for Texas Instruments ADC
|
||||
driver which is also a MFD client.
|
||||
|
||||
config TWL6030_GPADC
|
||||
tristate "TWL6030 GPADC (General Purpose A/D Converter) Support"
|
||||
depends on TWL4030_CORE
|
||||
default n
|
||||
help
|
||||
Say yes here if you want support for the TWL6030/TWL6032 General
|
||||
Purpose A/D Converter. This will add support for battery type
|
||||
detection, battery voltage and temperature measurement, die
|
||||
temperature measurement, system supply voltage, audio accessory,
|
||||
USB ID detection.
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called twl6030-gpadc.
|
||||
|
||||
config VIPERBOARD_ADC
|
||||
tristate "Viperboard ADC support"
|
||||
depends on MFD_VIPERBOARD && USB
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
# Makefile for IIO ADC drivers
|
||||
#
|
||||
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
|
||||
obj-$(CONFIG_AD7266) += ad7266.o
|
||||
obj-$(CONFIG_AD7298) += ad7298.o
|
||||
|
@ -15,6 +16,8 @@ obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
|
|||
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
|
||||
obj-$(CONFIG_MAX1363) += max1363.o
|
||||
obj-$(CONFIG_MCP320X) += mcp320x.o
|
||||
obj-$(CONFIG_NAU7802) += nau7802.o
|
||||
obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
|
||||
obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
|
||||
obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
|
||||
obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
|
||||
|
|
|
@ -399,17 +399,17 @@ static int ad7266_probe(struct spi_device *spi)
|
|||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
st->reg = regulator_get(&spi->dev, "vref");
|
||||
st->reg = devm_regulator_get(&spi->dev, "vref");
|
||||
if (!IS_ERR_OR_NULL(st->reg)) {
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
return ret;
|
||||
|
||||
ret = regulator_get_voltage(st->reg);
|
||||
if (ret < 0)
|
||||
|
@ -489,11 +489,6 @@ error_free_gpios:
|
|||
error_disable_reg:
|
||||
if (!IS_ERR_OR_NULL(st->reg))
|
||||
regulator_disable(st->reg);
|
||||
error_put_reg:
|
||||
if (!IS_ERR_OR_NULL(st->reg))
|
||||
regulator_put(st->reg);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -507,11 +502,8 @@ static int ad7266_remove(struct spi_device *spi)
|
|||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
if (!st->fixed_addr)
|
||||
gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
|
||||
if (!IS_ERR_OR_NULL(st->reg)) {
|
||||
if (!IS_ERR_OR_NULL(st->reg))
|
||||
regulator_disable(st->reg);
|
||||
regulator_put(st->reg);
|
||||
}
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -296,9 +296,10 @@ static int ad7298_probe(struct spi_device *spi)
|
|||
{
|
||||
struct ad7298_platform_data *pdata = spi->dev.platform_data;
|
||||
struct ad7298_state *st;
|
||||
struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
|
||||
struct iio_dev *indio_dev;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -308,14 +309,13 @@ static int ad7298_probe(struct spi_device *spi)
|
|||
st->ext_ref = AD7298_EXTREF;
|
||||
|
||||
if (st->ext_ref) {
|
||||
st->reg = regulator_get(&spi->dev, "vref");
|
||||
if (IS_ERR(st->reg)) {
|
||||
ret = PTR_ERR(st->reg);
|
||||
goto error_free;
|
||||
}
|
||||
st->reg = devm_regulator_get(&spi->dev, "vref");
|
||||
if (IS_ERR(st->reg))
|
||||
return PTR_ERR(st->reg);
|
||||
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
return ret;
|
||||
}
|
||||
|
||||
spi_set_drvdata(spi, indio_dev);
|
||||
|
@ -361,11 +361,6 @@ error_cleanup_ring:
|
|||
error_disable_reg:
|
||||
if (st->ext_ref)
|
||||
regulator_disable(st->reg);
|
||||
error_put_reg:
|
||||
if (st->ext_ref)
|
||||
regulator_put(st->reg);
|
||||
error_free:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -377,11 +372,8 @@ static int ad7298_remove(struct spi_device *spi)
|
|||
|
||||
iio_device_unregister(indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
if (st->ext_ref) {
|
||||
if (st->ext_ref)
|
||||
regulator_disable(st->reg);
|
||||
regulator_put(st->reg);
|
||||
}
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -213,24 +213,21 @@ static int ad7476_probe(struct spi_device *spi)
|
|||
struct iio_dev *indio_dev;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
st->chip_info =
|
||||
&ad7476_chip_info_tbl[spi_get_device_id(spi)->driver_data];
|
||||
|
||||
st->reg = regulator_get(&spi->dev, "vcc");
|
||||
if (IS_ERR(st->reg)) {
|
||||
ret = PTR_ERR(st->reg);
|
||||
goto error_free_dev;
|
||||
}
|
||||
st->reg = devm_regulator_get(&spi->dev, "vcc");
|
||||
if (IS_ERR(st->reg))
|
||||
return PTR_ERR(st->reg);
|
||||
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
return ret;
|
||||
|
||||
spi_set_drvdata(spi, indio_dev);
|
||||
|
||||
|
@ -268,12 +265,7 @@ error_ring_unregister:
|
|||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
error_disable_reg:
|
||||
regulator_disable(st->reg);
|
||||
error_put_reg:
|
||||
regulator_put(st->reg);
|
||||
error_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -285,8 +277,6 @@ static int ad7476_remove(struct spi_device *spi)
|
|||
iio_device_unregister(indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
regulator_disable(st->reg);
|
||||
regulator_put(st->reg);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -361,21 +361,19 @@ static int ad7791_probe(struct spi_device *spi)
|
|||
return -ENXIO;
|
||||
}
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
st->reg = regulator_get(&spi->dev, "refin");
|
||||
if (IS_ERR(st->reg)) {
|
||||
ret = PTR_ERR(st->reg);
|
||||
goto err_iio_free;
|
||||
}
|
||||
st->reg = devm_regulator_get(&spi->dev, "refin");
|
||||
if (IS_ERR(st->reg))
|
||||
return PTR_ERR(st->reg);
|
||||
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
return ret;
|
||||
|
||||
st->info = &ad7791_chip_infos[spi_get_device_id(spi)->driver_data];
|
||||
ad_sd_init(&st->sd, indio_dev, spi, &ad7791_sigma_delta_info);
|
||||
|
@ -410,10 +408,6 @@ error_remove_trigger:
|
|||
ad_sd_cleanup_buffer_and_trigger(indio_dev);
|
||||
error_disable_reg:
|
||||
regulator_disable(st->reg);
|
||||
error_put_reg:
|
||||
regulator_put(st->reg);
|
||||
err_iio_free:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -427,9 +421,6 @@ static int ad7791_remove(struct spi_device *spi)
|
|||
ad_sd_cleanup_buffer_and_trigger(indio_dev);
|
||||
|
||||
regulator_disable(st->reg);
|
||||
regulator_put(st->reg);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -757,7 +757,7 @@ static int ad7793_probe(struct spi_device *spi)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -766,15 +766,13 @@ static int ad7793_probe(struct spi_device *spi)
|
|||
ad_sd_init(&st->sd, indio_dev, spi, &ad7793_sigma_delta_info);
|
||||
|
||||
if (pdata->refsel != AD7793_REFSEL_INTERNAL) {
|
||||
st->reg = regulator_get(&spi->dev, "refin");
|
||||
if (IS_ERR(st->reg)) {
|
||||
ret = PTR_ERR(st->reg);
|
||||
goto error_device_free;
|
||||
}
|
||||
st->reg = devm_regulator_get(&spi->dev, "refin");
|
||||
if (IS_ERR(st->reg))
|
||||
return PTR_ERR(st->reg);
|
||||
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
return ret;
|
||||
|
||||
vref_mv = regulator_get_voltage(st->reg);
|
||||
if (vref_mv < 0) {
|
||||
|
@ -818,11 +816,6 @@ error_remove_trigger:
|
|||
error_disable_reg:
|
||||
if (pdata->refsel != AD7793_REFSEL_INTERNAL)
|
||||
regulator_disable(st->reg);
|
||||
error_put_reg:
|
||||
if (pdata->refsel != AD7793_REFSEL_INTERNAL)
|
||||
regulator_put(st->reg);
|
||||
error_device_free:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -836,12 +829,8 @@ static int ad7793_remove(struct spi_device *spi)
|
|||
iio_device_unregister(indio_dev);
|
||||
ad_sd_cleanup_buffer_and_trigger(indio_dev);
|
||||
|
||||
if (pdata->refsel != AD7793_REFSEL_INTERNAL) {
|
||||
if (pdata->refsel != AD7793_REFSEL_INTERNAL)
|
||||
regulator_disable(st->reg);
|
||||
regulator_put(st->reg);
|
||||
}
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -237,25 +237,24 @@ static int ad7887_probe(struct spi_device *spi)
|
|||
{
|
||||
struct ad7887_platform_data *pdata = spi->dev.platform_data;
|
||||
struct ad7887_state *st;
|
||||
struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
|
||||
struct iio_dev *indio_dev;
|
||||
uint8_t mode;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
if (!pdata || !pdata->use_onchip_ref) {
|
||||
st->reg = regulator_get(&spi->dev, "vref");
|
||||
if (IS_ERR(st->reg)) {
|
||||
ret = PTR_ERR(st->reg);
|
||||
goto error_free;
|
||||
}
|
||||
st->reg = devm_regulator_get(&spi->dev, "vref");
|
||||
if (IS_ERR(st->reg))
|
||||
return PTR_ERR(st->reg);
|
||||
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
return ret;
|
||||
}
|
||||
|
||||
st->chip_info =
|
||||
|
@ -331,11 +330,6 @@ error_unregister_ring:
|
|||
error_disable_reg:
|
||||
if (st->reg)
|
||||
regulator_disable(st->reg);
|
||||
error_put_reg:
|
||||
if (st->reg)
|
||||
regulator_put(st->reg);
|
||||
error_free:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -347,11 +341,8 @@ static int ad7887_remove(struct spi_device *spi)
|
|||
|
||||
iio_device_unregister(indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
if (st->reg) {
|
||||
if (st->reg)
|
||||
regulator_disable(st->reg);
|
||||
regulator_put(st->reg);
|
||||
}
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -275,10 +275,11 @@ static const struct iio_info ad7923_info = {
|
|||
static int ad7923_probe(struct spi_device *spi)
|
||||
{
|
||||
struct ad7923_state *st;
|
||||
struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
|
||||
struct iio_dev *indio_dev;
|
||||
const struct ad7923_chip_info *info;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -311,14 +312,13 @@ static int ad7923_probe(struct spi_device *spi)
|
|||
spi_message_add_tail(&st->scan_single_xfer[0], &st->scan_single_msg);
|
||||
spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg);
|
||||
|
||||
st->reg = regulator_get(&spi->dev, "refin");
|
||||
if (IS_ERR(st->reg)) {
|
||||
ret = PTR_ERR(st->reg);
|
||||
goto error_free;
|
||||
}
|
||||
st->reg = devm_regulator_get(&spi->dev, "refin");
|
||||
if (IS_ERR(st->reg))
|
||||
return PTR_ERR(st->reg);
|
||||
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
return ret;
|
||||
|
||||
ret = iio_triggered_buffer_setup(indio_dev, NULL,
|
||||
&ad7923_trigger_handler, NULL);
|
||||
|
@ -335,10 +335,6 @@ error_cleanup_ring:
|
|||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
error_disable_reg:
|
||||
regulator_disable(st->reg);
|
||||
error_put_reg:
|
||||
regulator_put(st->reg);
|
||||
error_free:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -351,8 +347,6 @@ static int ad7923_remove(struct spi_device *spi)
|
|||
iio_device_unregister(indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
regulator_disable(st->reg);
|
||||
regulator_put(st->reg);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,10 @@
|
|||
#define at91_adc_writel(st, reg, val) \
|
||||
(writel_relaxed(val, st->reg_base + reg))
|
||||
|
||||
struct at91_adc_caps {
|
||||
struct at91_adc_reg_desc registers;
|
||||
};
|
||||
|
||||
struct at91_adc_state {
|
||||
struct clk *adc_clk;
|
||||
u16 *buffer;
|
||||
|
@ -62,6 +66,7 @@ struct at91_adc_state {
|
|||
u32 res; /* resolution used for convertions */
|
||||
bool low_res; /* the resolution corresponds to the lowest one */
|
||||
wait_queue_head_t wq_data_avail;
|
||||
struct at91_adc_caps *caps;
|
||||
};
|
||||
|
||||
static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
|
||||
|
@ -429,6 +434,8 @@ ret:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id at91_adc_dt_ids[];
|
||||
|
||||
static int at91_adc_probe_dt(struct at91_adc_state *st,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
|
@ -441,6 +448,9 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
|
|||
if (!node)
|
||||
return -EINVAL;
|
||||
|
||||
st->caps = (struct at91_adc_caps *)
|
||||
of_match_device(at91_adc_dt_ids, &pdev->dev)->data;
|
||||
|
||||
st->use_external = of_property_read_bool(node, "atmel,adc-use-external-triggers");
|
||||
|
||||
if (of_property_read_u32(node, "atmel,adc-channels-used", &prop)) {
|
||||
|
@ -481,43 +491,7 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
|
|||
if (ret)
|
||||
goto error_ret;
|
||||
|
||||
st->registers = devm_kzalloc(&idev->dev,
|
||||
sizeof(struct at91_adc_reg_desc),
|
||||
GFP_KERNEL);
|
||||
if (!st->registers) {
|
||||
dev_err(&idev->dev, "Could not allocate register memory.\n");
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(node, "atmel,adc-channel-base", &prop)) {
|
||||
dev_err(&idev->dev, "Missing adc-channel-base property in the DT.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
st->registers->channel_base = prop;
|
||||
|
||||
if (of_property_read_u32(node, "atmel,adc-drdy-mask", &prop)) {
|
||||
dev_err(&idev->dev, "Missing adc-drdy-mask property in the DT.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
st->registers->drdy_mask = prop;
|
||||
|
||||
if (of_property_read_u32(node, "atmel,adc-status-register", &prop)) {
|
||||
dev_err(&idev->dev, "Missing adc-status-register property in the DT.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
st->registers->status_register = prop;
|
||||
|
||||
if (of_property_read_u32(node, "atmel,adc-trigger-register", &prop)) {
|
||||
dev_err(&idev->dev, "Missing adc-trigger-register property in the DT.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
st->registers->trigger_register = prop;
|
||||
|
||||
st->registers = &st->caps->registers;
|
||||
st->trigger_number = of_get_child_count(node);
|
||||
st->trigger_list = devm_kzalloc(&idev->dev, st->trigger_number *
|
||||
sizeof(struct at91_adc_trigger),
|
||||
|
@ -589,11 +563,9 @@ static int at91_adc_probe(struct platform_device *pdev)
|
|||
struct resource *res;
|
||||
u32 reg;
|
||||
|
||||
idev = iio_device_alloc(sizeof(struct at91_adc_state));
|
||||
if (idev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
idev = devm_iio_device_alloc(&pdev->dev, sizeof(struct at91_adc_state));
|
||||
if (!idev)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(idev);
|
||||
|
||||
|
@ -604,8 +576,7 @@ static int at91_adc_probe(struct platform_device *pdev)
|
|||
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "No platform data available.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_free_device;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, idev);
|
||||
|
@ -618,16 +589,14 @@ static int at91_adc_probe(struct platform_device *pdev)
|
|||
st->irq = platform_get_irq(pdev, 0);
|
||||
if (st->irq < 0) {
|
||||
dev_err(&pdev->dev, "No IRQ ID is designated\n");
|
||||
ret = -ENODEV;
|
||||
goto error_free_device;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
||||
st->reg_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(st->reg_base)) {
|
||||
ret = PTR_ERR(st->reg_base);
|
||||
goto error_free_device;
|
||||
return PTR_ERR(st->reg_base);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -642,7 +611,7 @@ static int at91_adc_probe(struct platform_device *pdev)
|
|||
idev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to allocate IRQ.\n");
|
||||
goto error_free_device;
|
||||
return ret;
|
||||
}
|
||||
|
||||
st->clk = devm_clk_get(&pdev->dev, "adc_clk");
|
||||
|
@ -703,8 +672,8 @@ static int at91_adc_probe(struct platform_device *pdev)
|
|||
shtim = round_up((st->sample_hold_time * adc_clk /
|
||||
1000000) - 1, 1);
|
||||
|
||||
reg = AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL;
|
||||
reg |= AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP;
|
||||
reg = AT91_ADC_PRESCAL_(prsc) & st->registers->mr_prescal_mask;
|
||||
reg |= AT91_ADC_STARTUP_(ticks) & st->registers->mr_startup_mask;
|
||||
if (st->low_res)
|
||||
reg |= AT91_ADC_LOWRES;
|
||||
if (st->sleep_mode)
|
||||
|
@ -752,9 +721,6 @@ error_disable_clk:
|
|||
clk_disable_unprepare(st->clk);
|
||||
error_free_irq:
|
||||
free_irq(st->irq, idev);
|
||||
error_free_device:
|
||||
iio_device_free(idev);
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -769,14 +735,49 @@ static int at91_adc_remove(struct platform_device *pdev)
|
|||
clk_disable_unprepare(st->adc_clk);
|
||||
clk_disable_unprepare(st->clk);
|
||||
free_irq(st->irq, idev);
|
||||
iio_device_free(idev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct at91_adc_caps at91sam9260_caps = {
|
||||
.registers = {
|
||||
.channel_base = AT91_ADC_CHR(0),
|
||||
.drdy_mask = AT91_ADC_DRDY,
|
||||
.status_register = AT91_ADC_SR,
|
||||
.trigger_register = AT91_ADC_TRGR_9260,
|
||||
.mr_prescal_mask = AT91_ADC_PRESCAL_9260,
|
||||
.mr_startup_mask = AT91_ADC_STARTUP_9260,
|
||||
},
|
||||
};
|
||||
|
||||
static struct at91_adc_caps at91sam9g45_caps = {
|
||||
.registers = {
|
||||
.channel_base = AT91_ADC_CHR(0),
|
||||
.drdy_mask = AT91_ADC_DRDY,
|
||||
.status_register = AT91_ADC_SR,
|
||||
.trigger_register = AT91_ADC_TRGR_9G45,
|
||||
.mr_prescal_mask = AT91_ADC_PRESCAL_9G45,
|
||||
.mr_startup_mask = AT91_ADC_STARTUP_9G45,
|
||||
},
|
||||
};
|
||||
|
||||
static struct at91_adc_caps at91sam9x5_caps = {
|
||||
.registers = {
|
||||
.channel_base = AT91_ADC_CDR0_9X5,
|
||||
.drdy_mask = AT91_ADC_SR_DRDY_9X5,
|
||||
.status_register = AT91_ADC_SR_9X5,
|
||||
.trigger_register = AT91_ADC_TRGR_9X5,
|
||||
/* prescal mask is same as 9G45 */
|
||||
.mr_prescal_mask = AT91_ADC_PRESCAL_9G45,
|
||||
.mr_startup_mask = AT91_ADC_STARTUP_9X5,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct of_device_id at91_adc_dt_ids[] = {
|
||||
{ .compatible = "atmel,at91sam9260-adc" },
|
||||
{ .compatible = "atmel,at91sam9260-adc", .data = &at91sam9260_caps },
|
||||
{ .compatible = "atmel,at91sam9g45-adc", .data = &at91sam9g45_caps },
|
||||
{ .compatible = "atmel,at91sam9x5-adc", .data = &at91sam9x5_caps },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, at91_adc_dt_ids);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/of_irq.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/machine.h>
|
||||
|
@ -261,7 +262,7 @@ static int exynos_adc_probe(struct platform_device *pdev)
|
|||
if (!np)
|
||||
return ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(struct exynos_adc));
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct exynos_adc));
|
||||
if (!indio_dev) {
|
||||
dev_err(&pdev->dev, "failed allocating iio device\n");
|
||||
return -ENOMEM;
|
||||
|
@ -271,23 +272,18 @@ static int exynos_adc_probe(struct platform_device *pdev)
|
|||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
info->regs = devm_ioremap_resource(&pdev->dev, mem);
|
||||
if (IS_ERR(info->regs)) {
|
||||
ret = PTR_ERR(info->regs);
|
||||
goto err_iio;
|
||||
}
|
||||
if (IS_ERR(info->regs))
|
||||
return PTR_ERR(info->regs);
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
info->enable_reg = devm_ioremap_resource(&pdev->dev, mem);
|
||||
if (IS_ERR(info->enable_reg)) {
|
||||
ret = PTR_ERR(info->enable_reg);
|
||||
goto err_iio;
|
||||
}
|
||||
if (IS_ERR(info->enable_reg))
|
||||
return PTR_ERR(info->enable_reg);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
dev_err(&pdev->dev, "no irq resource?\n");
|
||||
ret = irq;
|
||||
goto err_iio;
|
||||
return irq;
|
||||
}
|
||||
|
||||
info->irq = irq;
|
||||
|
@ -299,7 +295,7 @@ static int exynos_adc_probe(struct platform_device *pdev)
|
|||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed requesting irq, irq = %d\n",
|
||||
info->irq);
|
||||
goto err_iio;
|
||||
return ret;
|
||||
}
|
||||
|
||||
writel(1, info->enable_reg);
|
||||
|
@ -365,8 +361,6 @@ err_iio_dev:
|
|||
iio_device_unregister(indio_dev);
|
||||
err_irq:
|
||||
free_irq(info->irq, info);
|
||||
err_iio:
|
||||
iio_device_free(indio_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -382,7 +376,6 @@ static int exynos_adc_remove(struct platform_device *pdev)
|
|||
writel(0, info->enable_reg);
|
||||
iio_device_unregister(indio_dev);
|
||||
free_irq(info->irq, info);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -194,7 +194,7 @@ static int lp8788_adc_probe(struct platform_device *pdev)
|
|||
struct lp8788_adc *adc;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*adc));
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -205,7 +205,7 @@ static int lp8788_adc_probe(struct platform_device *pdev)
|
|||
indio_dev->dev.of_node = pdev->dev.of_node;
|
||||
ret = lp8788_iio_map_register(indio_dev, lp->pdata, adc);
|
||||
if (ret)
|
||||
goto err_iio_map;
|
||||
return ret;
|
||||
|
||||
mutex_init(&adc->lock);
|
||||
|
||||
|
@ -226,8 +226,6 @@ static int lp8788_adc_probe(struct platform_device *pdev)
|
|||
|
||||
err_iio_device:
|
||||
iio_map_array_unregister(indio_dev);
|
||||
err_iio_map:
|
||||
iio_device_free(indio_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -237,7 +235,6 @@ static int lp8788_adc_remove(struct platform_device *pdev)
|
|||
|
||||
iio_device_unregister(indio_dev);
|
||||
iio_map_array_unregister(indio_dev);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1498,16 +1498,15 @@ static int max1363_probe(struct i2c_client *client,
|
|||
struct iio_dev *indio_dev;
|
||||
struct regulator *vref;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(struct max1363_state));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_out;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&client->dev,
|
||||
sizeof(struct max1363_state));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
indio_dev->dev.of_node = client->dev.of_node;
|
||||
ret = iio_map_array_register(indio_dev, client->dev.platform_data);
|
||||
if (ret < 0)
|
||||
goto error_free_device;
|
||||
return ret;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
|
@ -1590,9 +1589,6 @@ error_disable_reg:
|
|||
regulator_disable(st->reg);
|
||||
error_unregister_map:
|
||||
iio_map_array_unregister(indio_dev);
|
||||
error_free_device:
|
||||
iio_device_free(indio_dev);
|
||||
error_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1607,7 +1603,6 @@ static int max1363_remove(struct i2c_client *client)
|
|||
regulator_disable(st->vref);
|
||||
regulator_disable(st->reg);
|
||||
iio_map_array_unregister(indio_dev);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -169,7 +169,7 @@ static int mcp320x_probe(struct spi_device *spi)
|
|||
const struct mcp3208_chip_info *chip_info;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*adc));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -193,15 +193,13 @@ static int mcp320x_probe(struct spi_device *spi)
|
|||
spi_message_init_with_transfers(&adc->msg, adc->transfer,
|
||||
ARRAY_SIZE(adc->transfer));
|
||||
|
||||
adc->reg = regulator_get(&spi->dev, "vref");
|
||||
if (IS_ERR(adc->reg)) {
|
||||
ret = PTR_ERR(adc->reg);
|
||||
goto iio_free;
|
||||
}
|
||||
adc->reg = devm_regulator_get(&spi->dev, "vref");
|
||||
if (IS_ERR(adc->reg))
|
||||
return PTR_ERR(adc->reg);
|
||||
|
||||
ret = regulator_enable(adc->reg);
|
||||
if (ret < 0)
|
||||
goto reg_free;
|
||||
return ret;
|
||||
|
||||
mutex_init(&adc->lock);
|
||||
|
||||
|
@ -213,10 +211,6 @@ static int mcp320x_probe(struct spi_device *spi)
|
|||
|
||||
reg_disable:
|
||||
regulator_disable(adc->reg);
|
||||
reg_free:
|
||||
regulator_put(adc->reg);
|
||||
iio_free:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -228,8 +222,6 @@ static int mcp320x_remove(struct spi_device *spi)
|
|||
|
||||
iio_device_unregister(indio_dev);
|
||||
regulator_disable(adc->reg);
|
||||
regulator_put(adc->reg);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,581 @@
|
|||
/*
|
||||
* Driver for the Nuvoton NAU7802 ADC
|
||||
*
|
||||
* Copyright 2013 Free Electrons
|
||||
*
|
||||
* Licensed under the GPLv2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/log2.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
|
||||
#define NAU7802_REG_PUCTRL 0x00
|
||||
#define NAU7802_PUCTRL_RR(x) (x << 0)
|
||||
#define NAU7802_PUCTRL_RR_BIT NAU7802_PUCTRL_RR(1)
|
||||
#define NAU7802_PUCTRL_PUD(x) (x << 1)
|
||||
#define NAU7802_PUCTRL_PUD_BIT NAU7802_PUCTRL_PUD(1)
|
||||
#define NAU7802_PUCTRL_PUA(x) (x << 2)
|
||||
#define NAU7802_PUCTRL_PUA_BIT NAU7802_PUCTRL_PUA(1)
|
||||
#define NAU7802_PUCTRL_PUR(x) (x << 3)
|
||||
#define NAU7802_PUCTRL_PUR_BIT NAU7802_PUCTRL_PUR(1)
|
||||
#define NAU7802_PUCTRL_CS(x) (x << 4)
|
||||
#define NAU7802_PUCTRL_CS_BIT NAU7802_PUCTRL_CS(1)
|
||||
#define NAU7802_PUCTRL_CR(x) (x << 5)
|
||||
#define NAU7802_PUCTRL_CR_BIT NAU7802_PUCTRL_CR(1)
|
||||
#define NAU7802_PUCTRL_AVDDS(x) (x << 7)
|
||||
#define NAU7802_PUCTRL_AVDDS_BIT NAU7802_PUCTRL_AVDDS(1)
|
||||
#define NAU7802_REG_CTRL1 0x01
|
||||
#define NAU7802_CTRL1_VLDO(x) (x << 3)
|
||||
#define NAU7802_CTRL1_GAINS(x) (x)
|
||||
#define NAU7802_CTRL1_GAINS_BITS 0x07
|
||||
#define NAU7802_REG_CTRL2 0x02
|
||||
#define NAU7802_CTRL2_CHS(x) (x << 7)
|
||||
#define NAU7802_CTRL2_CRS(x) (x << 4)
|
||||
#define NAU7802_SAMP_FREQ_320 0x07
|
||||
#define NAU7802_CTRL2_CHS_BIT NAU7802_CTRL2_CHS(1)
|
||||
#define NAU7802_REG_ADC_B2 0x12
|
||||
#define NAU7802_REG_ADC_B1 0x13
|
||||
#define NAU7802_REG_ADC_B0 0x14
|
||||
#define NAU7802_REG_ADC_CTRL 0x15
|
||||
|
||||
#define NAU7802_MIN_CONVERSIONS 6
|
||||
|
||||
struct nau7802_state {
|
||||
struct i2c_client *client;
|
||||
s32 last_value;
|
||||
struct mutex lock;
|
||||
struct mutex data_lock;
|
||||
u32 vref_mv;
|
||||
u32 conversion_count;
|
||||
u32 min_conversions;
|
||||
u8 sample_rate;
|
||||
u32 scale_avail[8];
|
||||
struct completion value_ok;
|
||||
};
|
||||
|
||||
#define NAU7802_CHANNEL(chan) { \
|
||||
.type = IIO_VOLTAGE, \
|
||||
.indexed = 1, \
|
||||
.channel = (chan), \
|
||||
.scan_index = (chan), \
|
||||
.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 nau7802_chan_array[] = {
|
||||
NAU7802_CHANNEL(0),
|
||||
NAU7802_CHANNEL(1),
|
||||
};
|
||||
|
||||
static const u16 nau7802_sample_freq_avail[] = {10, 20, 40, 80,
|
||||
10, 10, 10, 320};
|
||||
|
||||
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 40 80 320");
|
||||
|
||||
static struct attribute *nau7802_attributes[] = {
|
||||
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group nau7802_attribute_group = {
|
||||
.attrs = nau7802_attributes,
|
||||
};
|
||||
|
||||
static int nau7802_set_gain(struct nau7802_state *st, int gain)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&st->lock);
|
||||
st->conversion_count = 0;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(st->client, NAU7802_REG_CTRL1);
|
||||
if (ret < 0)
|
||||
goto nau7802_sysfs_set_gain_out;
|
||||
ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_CTRL1,
|
||||
(ret & (~NAU7802_CTRL1_GAINS_BITS)) |
|
||||
gain);
|
||||
|
||||
nau7802_sysfs_set_gain_out:
|
||||
mutex_unlock(&st->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nau7802_read_conversion(struct nau7802_state *st)
|
||||
{
|
||||
int data;
|
||||
|
||||
mutex_lock(&st->data_lock);
|
||||
data = i2c_smbus_read_byte_data(st->client, NAU7802_REG_ADC_B2);
|
||||
if (data < 0)
|
||||
goto nau7802_read_conversion_out;
|
||||
st->last_value = data << 16;
|
||||
|
||||
data = i2c_smbus_read_byte_data(st->client, NAU7802_REG_ADC_B1);
|
||||
if (data < 0)
|
||||
goto nau7802_read_conversion_out;
|
||||
st->last_value |= data << 8;
|
||||
|
||||
data = i2c_smbus_read_byte_data(st->client, NAU7802_REG_ADC_B0);
|
||||
if (data < 0)
|
||||
goto nau7802_read_conversion_out;
|
||||
st->last_value |= data;
|
||||
|
||||
st->last_value = sign_extend32(st->last_value, 23);
|
||||
|
||||
nau7802_read_conversion_out:
|
||||
mutex_unlock(&st->data_lock);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Conversions are synchronised on the rising edge of NAU7802_PUCTRL_CS_BIT
|
||||
*/
|
||||
static int nau7802_sync(struct nau7802_state *st)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(st->client, NAU7802_REG_PUCTRL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_PUCTRL,
|
||||
ret | NAU7802_PUCTRL_CS_BIT);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t nau7802_eoc_trigger(int irq, void *private)
|
||||
{
|
||||
struct iio_dev *indio_dev = private;
|
||||
struct nau7802_state *st = iio_priv(indio_dev);
|
||||
int status;
|
||||
|
||||
status = i2c_smbus_read_byte_data(st->client, NAU7802_REG_PUCTRL);
|
||||
if (status < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (!(status & NAU7802_PUCTRL_CR_BIT))
|
||||
return IRQ_NONE;
|
||||
|
||||
if (nau7802_read_conversion(st) < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
/*
|
||||
* Because there is actually only one ADC for both channels, we have to
|
||||
* wait for enough conversions to happen before getting a significant
|
||||
* value when changing channels and the values are far apart.
|
||||
*/
|
||||
if (st->conversion_count < NAU7802_MIN_CONVERSIONS)
|
||||
st->conversion_count++;
|
||||
if (st->conversion_count >= NAU7802_MIN_CONVERSIONS)
|
||||
complete_all(&st->value_ok);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int nau7802_read_irq(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val)
|
||||
{
|
||||
struct nau7802_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
INIT_COMPLETION(st->value_ok);
|
||||
enable_irq(st->client->irq);
|
||||
|
||||
nau7802_sync(st);
|
||||
|
||||
/* read registers to ensure we flush everything */
|
||||
ret = nau7802_read_conversion(st);
|
||||
if (ret < 0)
|
||||
goto read_chan_info_failure;
|
||||
|
||||
/* Wait for a conversion to finish */
|
||||
ret = wait_for_completion_interruptible_timeout(&st->value_ok,
|
||||
msecs_to_jiffies(1000));
|
||||
if (ret == 0)
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
if (ret < 0)
|
||||
goto read_chan_info_failure;
|
||||
|
||||
disable_irq(st->client->irq);
|
||||
|
||||
*val = st->last_value;
|
||||
|
||||
return IIO_VAL_INT;
|
||||
|
||||
read_chan_info_failure:
|
||||
disable_irq(st->client->irq);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nau7802_read_poll(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val)
|
||||
{
|
||||
struct nau7802_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
nau7802_sync(st);
|
||||
|
||||
/* read registers to ensure we flush everything */
|
||||
ret = nau7802_read_conversion(st);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Because there is actually only one ADC for both channels, we have to
|
||||
* wait for enough conversions to happen before getting a significant
|
||||
* value when changing channels and the values are far appart.
|
||||
*/
|
||||
do {
|
||||
ret = i2c_smbus_read_byte_data(st->client, NAU7802_REG_PUCTRL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
while (!(ret & NAU7802_PUCTRL_CR_BIT)) {
|
||||
if (st->sample_rate != NAU7802_SAMP_FREQ_320)
|
||||
msleep(20);
|
||||
else
|
||||
mdelay(4);
|
||||
ret = i2c_smbus_read_byte_data(st->client,
|
||||
NAU7802_REG_PUCTRL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nau7802_read_conversion(st);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (st->conversion_count < NAU7802_MIN_CONVERSIONS)
|
||||
st->conversion_count++;
|
||||
} while (st->conversion_count < NAU7802_MIN_CONVERSIONS);
|
||||
|
||||
*val = st->last_value;
|
||||
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
|
||||
static int nau7802_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct nau7802_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
mutex_lock(&st->lock);
|
||||
/*
|
||||
* Select the channel to use
|
||||
* - Channel 1 is value 0 in the CHS register
|
||||
* - Channel 2 is value 1 in the CHS register
|
||||
*/
|
||||
ret = i2c_smbus_read_byte_data(st->client, NAU7802_REG_CTRL2);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&st->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (((ret & NAU7802_CTRL2_CHS_BIT) && !chan->channel) ||
|
||||
(!(ret & NAU7802_CTRL2_CHS_BIT) &&
|
||||
chan->channel)) {
|
||||
st->conversion_count = 0;
|
||||
ret = i2c_smbus_write_byte_data(st->client,
|
||||
NAU7802_REG_CTRL2,
|
||||
NAU7802_CTRL2_CHS(chan->channel) |
|
||||
NAU7802_CTRL2_CRS(st->sample_rate));
|
||||
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&st->lock);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (st->client->irq)
|
||||
ret = nau7802_read_irq(indio_dev, chan, val);
|
||||
else
|
||||
ret = nau7802_read_poll(indio_dev, chan, val);
|
||||
|
||||
mutex_unlock(&st->lock);
|
||||
return ret;
|
||||
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
ret = i2c_smbus_read_byte_data(st->client, NAU7802_REG_CTRL1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* We have 24 bits of signed data, that means 23 bits of data
|
||||
* plus the sign bit
|
||||
*/
|
||||
*val = st->vref_mv;
|
||||
*val2 = 23 + (ret & NAU7802_CTRL1_GAINS_BITS);
|
||||
|
||||
return IIO_VAL_FRACTIONAL_LOG2;
|
||||
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
*val = nau7802_sample_freq_avail[st->sample_rate];
|
||||
*val2 = 0;
|
||||
return IIO_VAL_INT;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int nau7802_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val, int val2, long mask)
|
||||
{
|
||||
struct nau7802_state *st = iio_priv(indio_dev);
|
||||
int i, ret;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
|
||||
if (val2 == st->scale_avail[i])
|
||||
return nau7802_set_gain(st, i);
|
||||
|
||||
break;
|
||||
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
for (i = 0; i < ARRAY_SIZE(nau7802_sample_freq_avail); i++)
|
||||
if (val == nau7802_sample_freq_avail[i]) {
|
||||
mutex_lock(&st->lock);
|
||||
st->sample_rate = i;
|
||||
st->conversion_count = 0;
|
||||
ret = i2c_smbus_write_byte_data(st->client,
|
||||
NAU7802_REG_CTRL2,
|
||||
NAU7802_CTRL2_CRS(st->sample_rate));
|
||||
mutex_unlock(&st->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int nau7802_write_raw_get_fmt(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
long mask)
|
||||
{
|
||||
return IIO_VAL_INT_PLUS_NANO;
|
||||
}
|
||||
|
||||
static const struct iio_info nau7802_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = &nau7802_read_raw,
|
||||
.write_raw = &nau7802_write_raw,
|
||||
.write_raw_get_fmt = nau7802_write_raw_get_fmt,
|
||||
.attrs = &nau7802_attribute_group,
|
||||
};
|
||||
|
||||
static int nau7802_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct iio_dev *indio_dev;
|
||||
struct nau7802_state *st;
|
||||
struct device_node *np = client->dev.of_node;
|
||||
int i, ret;
|
||||
u8 data;
|
||||
u32 tmp = 0;
|
||||
|
||||
if (!client->dev.of_node) {
|
||||
dev_err(&client->dev, "No device tree node available.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
|
||||
indio_dev->dev.parent = &client->dev;
|
||||
indio_dev->name = dev_name(&client->dev);
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->info = &nau7802_info;
|
||||
|
||||
st->client = client;
|
||||
|
||||
/* Reset the device */
|
||||
ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_PUCTRL,
|
||||
NAU7802_PUCTRL_RR_BIT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Enter normal operation mode */
|
||||
ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_PUCTRL,
|
||||
NAU7802_PUCTRL_PUD_BIT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* After about 200 usecs, the device should be ready and then
|
||||
* the Power Up bit will be set to 1. If not, wait for it.
|
||||
*/
|
||||
udelay(210);
|
||||
ret = i2c_smbus_read_byte_data(st->client, NAU7802_REG_PUCTRL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (!(ret & NAU7802_PUCTRL_PUR_BIT))
|
||||
return ret;
|
||||
|
||||
of_property_read_u32(np, "nuvoton,vldo", &tmp);
|
||||
st->vref_mv = tmp;
|
||||
|
||||
data = NAU7802_PUCTRL_PUD_BIT | NAU7802_PUCTRL_PUA_BIT |
|
||||
NAU7802_PUCTRL_CS_BIT;
|
||||
if (tmp >= 2400)
|
||||
data |= NAU7802_PUCTRL_AVDDS_BIT;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_PUCTRL, data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_ADC_CTRL, 0x30);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (tmp >= 2400) {
|
||||
data = NAU7802_CTRL1_VLDO((4500 - tmp) / 300);
|
||||
ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_CTRL1,
|
||||
data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Populate available ADC input ranges */
|
||||
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
|
||||
st->scale_avail[i] = (((u64)st->vref_mv) * 1000000000ULL)
|
||||
>> (23 + i);
|
||||
|
||||
init_completion(&st->value_ok);
|
||||
|
||||
/*
|
||||
* The ADC fires continuously and we can't do anything about
|
||||
* it. So we need to have the IRQ disabled by default, and we
|
||||
* will enable them back when we will need them..
|
||||
*/
|
||||
if (client->irq) {
|
||||
ret = request_threaded_irq(client->irq,
|
||||
NULL,
|
||||
nau7802_eoc_trigger,
|
||||
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
|
||||
client->dev.driver->name,
|
||||
indio_dev);
|
||||
if (ret) {
|
||||
/*
|
||||
* What may happen here is that our IRQ controller is
|
||||
* not able to get level interrupt but this is required
|
||||
* by this ADC as when going over 40 sample per second,
|
||||
* the interrupt line may stay high between conversions.
|
||||
* So, we continue no matter what but we switch to
|
||||
* polling mode.
|
||||
*/
|
||||
dev_info(&client->dev,
|
||||
"Failed to allocate IRQ, using polling mode\n");
|
||||
client->irq = 0;
|
||||
} else
|
||||
disable_irq(client->irq);
|
||||
}
|
||||
|
||||
if (!client->irq) {
|
||||
/*
|
||||
* We are polling, use the fastest sample rate by
|
||||
* default
|
||||
*/
|
||||
st->sample_rate = NAU7802_SAMP_FREQ_320;
|
||||
ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_CTRL2,
|
||||
NAU7802_CTRL2_CRS(st->sample_rate));
|
||||
if (ret)
|
||||
goto error_free_irq;
|
||||
}
|
||||
|
||||
/* Setup the ADC channels available on the board */
|
||||
indio_dev->num_channels = ARRAY_SIZE(nau7802_chan_array);
|
||||
indio_dev->channels = nau7802_chan_array;
|
||||
|
||||
mutex_init(&st->lock);
|
||||
mutex_init(&st->data_lock);
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "Couldn't register the device.\n");
|
||||
goto error_device_register;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_device_register:
|
||||
mutex_destroy(&st->lock);
|
||||
mutex_destroy(&st->data_lock);
|
||||
error_free_irq:
|
||||
if (client->irq)
|
||||
free_irq(client->irq, indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nau7802_remove(struct i2c_client *client)
|
||||
{
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
||||
struct nau7802_state *st = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
mutex_destroy(&st->lock);
|
||||
mutex_destroy(&st->data_lock);
|
||||
if (client->irq)
|
||||
free_irq(client->irq, indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id nau7802_i2c_id[] = {
|
||||
{ "nau7802", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, nau7802_i2c_id);
|
||||
|
||||
static const struct of_device_id nau7802_dt_ids[] = {
|
||||
{ .compatible = "nuvoton,nau7802" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, nau7802_dt_ids);
|
||||
|
||||
static struct i2c_driver nau7802_driver = {
|
||||
.probe = nau7802_probe,
|
||||
.remove = nau7802_remove,
|
||||
.id_table = nau7802_i2c_id,
|
||||
.driver = {
|
||||
.name = "nau7802",
|
||||
.of_match_table = of_match_ptr(nau7802_dt_ids),
|
||||
},
|
||||
};
|
||||
|
||||
module_i2c_driver(nau7802_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Nuvoton NAU7802 ADC Driver");
|
||||
MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
|
||||
MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
|
|
@ -74,22 +74,20 @@ static int adc081c_probe(struct i2c_client *client,
|
|||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
|
||||
return -ENODEV;
|
||||
|
||||
iio = iio_device_alloc(sizeof(*adc));
|
||||
iio = devm_iio_device_alloc(&client->dev, sizeof(*adc));
|
||||
if (!iio)
|
||||
return -ENOMEM;
|
||||
|
||||
adc = iio_priv(iio);
|
||||
adc->i2c = client;
|
||||
|
||||
adc->ref = regulator_get(&client->dev, "vref");
|
||||
if (IS_ERR(adc->ref)) {
|
||||
err = PTR_ERR(adc->ref);
|
||||
goto iio_free;
|
||||
}
|
||||
adc->ref = devm_regulator_get(&client->dev, "vref");
|
||||
if (IS_ERR(adc->ref))
|
||||
return PTR_ERR(adc->ref);
|
||||
|
||||
err = regulator_enable(adc->ref);
|
||||
if (err < 0)
|
||||
goto regulator_put;
|
||||
return err;
|
||||
|
||||
iio->dev.parent = &client->dev;
|
||||
iio->name = dev_name(&client->dev);
|
||||
|
@ -109,10 +107,6 @@ static int adc081c_probe(struct i2c_client *client,
|
|||
|
||||
regulator_disable:
|
||||
regulator_disable(adc->ref);
|
||||
regulator_put:
|
||||
regulator_put(adc->ref);
|
||||
iio_free:
|
||||
iio_device_free(iio);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -124,8 +118,6 @@ static int adc081c_remove(struct i2c_client *client)
|
|||
|
||||
iio_device_unregister(iio);
|
||||
regulator_disable(adc->ref);
|
||||
regulator_put(adc->ref);
|
||||
iio_device_free(iio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -216,11 +216,11 @@ static int tiadc_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(struct tiadc_device));
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev,
|
||||
sizeof(struct tiadc_device));
|
||||
if (indio_dev == NULL) {
|
||||
dev_err(&pdev->dev, "failed to allocate iio device\n");
|
||||
err = -ENOMEM;
|
||||
goto err_ret;
|
||||
return -ENOMEM;
|
||||
}
|
||||
adc_dev = iio_priv(indio_dev);
|
||||
|
||||
|
@ -241,7 +241,7 @@ static int tiadc_probe(struct platform_device *pdev)
|
|||
|
||||
err = tiadc_channel_init(indio_dev, adc_dev->channels);
|
||||
if (err < 0)
|
||||
goto err_free_device;
|
||||
return err;
|
||||
|
||||
err = iio_device_register(indio_dev);
|
||||
if (err)
|
||||
|
@ -253,9 +253,6 @@ static int tiadc_probe(struct platform_device *pdev)
|
|||
|
||||
err_free_channels:
|
||||
tiadc_channels_remove(indio_dev);
|
||||
err_free_device:
|
||||
iio_device_free(indio_dev);
|
||||
err_ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -271,8 +268,6 @@ static int tiadc_remove(struct platform_device *pdev)
|
|||
step_en = get_adc_step_mask(adc_dev);
|
||||
am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -124,7 +124,7 @@ static int vprbrd_adc_probe(struct platform_device *pdev)
|
|||
int ret;
|
||||
|
||||
/* registering iio */
|
||||
indio_dev = iio_device_alloc(sizeof(*adc));
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
|
||||
if (!indio_dev) {
|
||||
dev_err(&pdev->dev, "failed allocating iio device\n");
|
||||
return -ENOMEM;
|
||||
|
@ -142,16 +142,12 @@ static int vprbrd_adc_probe(struct platform_device *pdev)
|
|||
ret = iio_device_register(indio_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "could not register iio (adc)");
|
||||
goto error;
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
iio_device_free(indio_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vprbrd_adc_remove(struct platform_device *pdev)
|
||||
|
@ -159,7 +155,6 @@ static int vprbrd_adc_remove(struct platform_device *pdev)
|
|||
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# Gain Amplifiers, etc.
|
||||
#
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
|
||||
menu "Amplifiers"
|
||||
|
||||
config AD8366
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
# Makefile iio/amplifiers
|
||||
#
|
||||
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
obj-$(CONFIG_AD8366) += ad8366.o
|
||||
|
|
|
@ -139,17 +139,17 @@ static int ad8366_probe(struct spi_device *spi)
|
|||
struct ad8366_state *st;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
st->reg = regulator_get(&spi->dev, "vcc");
|
||||
st->reg = devm_regulator_get(&spi->dev, "vcc");
|
||||
if (!IS_ERR(st->reg)) {
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
return ret;
|
||||
}
|
||||
|
||||
spi_set_drvdata(spi, indio_dev);
|
||||
|
@ -173,11 +173,6 @@ static int ad8366_probe(struct spi_device *spi)
|
|||
error_disable_reg:
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_disable(st->reg);
|
||||
error_put_reg:
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_put(st->reg);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -195,8 +190,6 @@ static int ad8366_remove(struct spi_device *spi)
|
|||
regulator_put(reg);
|
||||
}
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,5 +6,6 @@
|
|||
# instead of duplicating in each module.
|
||||
#
|
||||
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
obj-y += hid-sensors/
|
||||
obj-y += st_sensors/
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
static inline u32 st_sensors_get_unaligned_le24(const u8 *p)
|
||||
{
|
||||
return ((s32)((p[0] | p[1] << 8 | p[2] << 16) << 8) >> 8);
|
||||
return (s32)((p[0] | p[1] << 8 | p[2] << 16) << 8) >> 8;
|
||||
}
|
||||
|
||||
static int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
|
||||
|
@ -118,7 +118,7 @@ st_sensors_match_odr_error:
|
|||
}
|
||||
|
||||
static int st_sensors_set_fullscale(struct iio_dev *indio_dev,
|
||||
unsigned int fs)
|
||||
unsigned int fs)
|
||||
{
|
||||
int err, i = 0;
|
||||
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
||||
|
@ -198,13 +198,39 @@ int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable)
|
|||
}
|
||||
EXPORT_SYMBOL(st_sensors_set_axis_enable);
|
||||
|
||||
int st_sensors_init_sensor(struct iio_dev *indio_dev)
|
||||
int st_sensors_init_sensor(struct iio_dev *indio_dev,
|
||||
struct st_sensors_platform_data *pdata)
|
||||
{
|
||||
int err;
|
||||
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
||||
|
||||
mutex_init(&sdata->tb.buf_lock);
|
||||
|
||||
switch (pdata->drdy_int_pin) {
|
||||
case 1:
|
||||
if (sdata->sensor->drdy_irq.mask_int1 == 0) {
|
||||
dev_err(&indio_dev->dev,
|
||||
"DRDY on INT1 not available.\n");
|
||||
err = -EINVAL;
|
||||
goto init_error;
|
||||
}
|
||||
sdata->drdy_int_pin = 1;
|
||||
break;
|
||||
case 2:
|
||||
if (sdata->sensor->drdy_irq.mask_int2 == 0) {
|
||||
dev_err(&indio_dev->dev,
|
||||
"DRDY on INT2 not available.\n");
|
||||
err = -EINVAL;
|
||||
goto init_error;
|
||||
}
|
||||
sdata->drdy_int_pin = 2;
|
||||
break;
|
||||
default:
|
||||
dev_err(&indio_dev->dev, "DRDY on pdata not valid.\n");
|
||||
err = -EINVAL;
|
||||
goto init_error;
|
||||
}
|
||||
|
||||
err = st_sensors_set_enable(indio_dev, false);
|
||||
if (err < 0)
|
||||
goto init_error;
|
||||
|
@ -234,6 +260,7 @@ EXPORT_SYMBOL(st_sensors_init_sensor);
|
|||
int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable)
|
||||
{
|
||||
int err;
|
||||
u8 drdy_mask;
|
||||
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
||||
|
||||
/* Enable/Disable the interrupt generator 1. */
|
||||
|
@ -245,10 +272,14 @@ int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable)
|
|||
goto st_accel_set_dataready_irq_error;
|
||||
}
|
||||
|
||||
if (sdata->drdy_int_pin == 1)
|
||||
drdy_mask = sdata->sensor->drdy_irq.mask_int1;
|
||||
else
|
||||
drdy_mask = sdata->sensor->drdy_irq.mask_int2;
|
||||
|
||||
/* Enable/Disable the interrupt generator for data ready. */
|
||||
err = st_sensors_write_data_with_mask(indio_dev,
|
||||
sdata->sensor->drdy_irq.addr,
|
||||
sdata->sensor->drdy_irq.mask, (int)enable);
|
||||
sdata->sensor->drdy_irq.addr, drdy_mask, (int)enable);
|
||||
|
||||
st_accel_set_dataready_irq_error:
|
||||
return err;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# DAC drivers
|
||||
#
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
|
||||
menu "Digital to analog converters"
|
||||
|
||||
config AD5064
|
||||
|
@ -15,7 +17,7 @@ config AD5064
|
|||
module will be called ad5064.
|
||||
|
||||
config AD5360
|
||||
tristate "Analog Devices Analog Devices AD5360/61/62/63/70/71/73 DAC driver"
|
||||
tristate "Analog Devices AD5360/61/62/63/70/71/73 DAC driver"
|
||||
depends on SPI
|
||||
help
|
||||
Say yes here to build support for Analog Devices AD5360, AD5361,
|
||||
|
@ -48,13 +50,6 @@ config AD5421
|
|||
To compile this driver as module choose M here: the module will be called
|
||||
ad5421.
|
||||
|
||||
config AD5624R_SPI
|
||||
tristate "Analog Devices AD5624/44/64R DAC spi driver"
|
||||
depends on SPI
|
||||
help
|
||||
Say yes here to build support for Analog Devices AD5624R, AD5644R and
|
||||
AD5664R converters (DAC). This driver uses the common SPI interface.
|
||||
|
||||
config AD5446
|
||||
tristate "Analog Devices AD5446 and similar single channel DACs driver"
|
||||
depends on (SPI_MASTER && I2C!=m) || I2C
|
||||
|
@ -68,7 +63,7 @@ config AD5446
|
|||
module will be called ad5446.
|
||||
|
||||
config AD5449
|
||||
tristate "Analog Device AD5449 and similar DACs driver"
|
||||
tristate "Analog Devices AD5449 and similar DACs driver"
|
||||
depends on SPI_MASTER
|
||||
help
|
||||
Say yes here to build support for Analog Devices AD5415, AD5426, AD5429,
|
||||
|
@ -87,6 +82,24 @@ config AD5504
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad5504.
|
||||
|
||||
config AD5624R_SPI
|
||||
tristate "Analog Devices AD5624/44/64R DAC spi driver"
|
||||
depends on SPI
|
||||
help
|
||||
Say yes here to build support for Analog Devices AD5624R, AD5644R and
|
||||
AD5664R converters (DAC). This driver uses the common SPI interface.
|
||||
|
||||
config AD5686
|
||||
tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver"
|
||||
depends on SPI
|
||||
help
|
||||
Say yes here to build support for Analog Devices AD5686R, AD5685R,
|
||||
AD5684R, AD5791 Voltage Output Digital to
|
||||
Analog Converter.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad5686.
|
||||
|
||||
config AD5755
|
||||
tristate "Analog Devices AD5755/AD5755-1/AD5757/AD5735/AD5737 DAC driver"
|
||||
depends on SPI_MASTER
|
||||
|
@ -119,19 +132,8 @@ config AD5791
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad5791.
|
||||
|
||||
config AD5686
|
||||
tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver"
|
||||
depends on SPI
|
||||
help
|
||||
Say yes here to build support for Analog Devices AD5686R, AD5685R,
|
||||
AD5684R, AD5791 Voltage Output Digital to
|
||||
Analog Converter.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad5686.
|
||||
|
||||
config AD7303
|
||||
tristate "Analog Devices Analog Devices AD7303 DAC driver"
|
||||
tristate "Analog Devices AD7303 DAC driver"
|
||||
depends on SPI
|
||||
help
|
||||
Say yes here to build support for Analog Devices AD7303 Digital to Analog
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
# Makefile for industrial I/O DAC drivers
|
||||
#
|
||||
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
obj-$(CONFIG_AD5360) += ad5360.o
|
||||
obj-$(CONFIG_AD5380) += ad5380.o
|
||||
obj-$(CONFIG_AD5421) += ad5421.o
|
||||
|
|
|
@ -442,7 +442,7 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type,
|
|||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -456,23 +456,23 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type,
|
|||
for (i = 0; i < ad5064_num_vref(st); ++i)
|
||||
st->vref_reg[i].supply = ad5064_vref_name(st, i);
|
||||
|
||||
ret = regulator_bulk_get(dev, ad5064_num_vref(st),
|
||||
ret = devm_regulator_bulk_get(dev, ad5064_num_vref(st),
|
||||
st->vref_reg);
|
||||
if (ret) {
|
||||
if (!st->chip_info->internal_vref)
|
||||
goto error_free;
|
||||
return ret;
|
||||
st->use_internal_vref = true;
|
||||
ret = ad5064_write(st, AD5064_CMD_CONFIG, 0,
|
||||
AD5064_CONFIG_INT_VREF_ENABLE, 0);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable internal vref: %d\n",
|
||||
ret);
|
||||
goto error_free;
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg);
|
||||
if (ret)
|
||||
goto error_free_reg;
|
||||
return ret;
|
||||
}
|
||||
|
||||
indio_dev->dev.parent = dev;
|
||||
|
@ -498,11 +498,6 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type,
|
|||
error_disable_reg:
|
||||
if (!st->use_internal_vref)
|
||||
regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg);
|
||||
error_free_reg:
|
||||
if (!st->use_internal_vref)
|
||||
regulator_bulk_free(ad5064_num_vref(st), st->vref_reg);
|
||||
error_free:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -514,12 +509,8 @@ static int ad5064_remove(struct device *dev)
|
|||
|
||||
iio_device_unregister(indio_dev);
|
||||
|
||||
if (!st->use_internal_vref) {
|
||||
if (!st->use_internal_vref)
|
||||
regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg);
|
||||
regulator_bulk_free(ad5064_num_vref(st), st->vref_reg);
|
||||
}
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -459,7 +459,7 @@ static int ad5360_probe(struct spi_device *spi)
|
|||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
dev_err(&spi->dev, "Failed to allocate iio device\n");
|
||||
return -ENOMEM;
|
||||
|
@ -480,13 +480,13 @@ static int ad5360_probe(struct spi_device *spi)
|
|||
ret = ad5360_alloc_channels(indio_dev);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed to allocate channel spec: %d\n", ret);
|
||||
goto error_free;
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < st->chip_info->num_vrefs; ++i)
|
||||
st->vref_reg[i].supply = ad5360_vref_name[i];
|
||||
|
||||
ret = regulator_bulk_get(&st->spi->dev, st->chip_info->num_vrefs,
|
||||
ret = devm_regulator_bulk_get(&st->spi->dev, st->chip_info->num_vrefs,
|
||||
st->vref_reg);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed to request vref regulators: %d\n", ret);
|
||||
|
@ -496,7 +496,7 @@ static int ad5360_probe(struct spi_device *spi)
|
|||
ret = regulator_bulk_enable(st->chip_info->num_vrefs, st->vref_reg);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed to enable vref regulators: %d\n", ret);
|
||||
goto error_free_reg;
|
||||
goto error_free_channels;
|
||||
}
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
|
@ -509,12 +509,8 @@ static int ad5360_probe(struct spi_device *spi)
|
|||
|
||||
error_disable_reg:
|
||||
regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg);
|
||||
error_free_reg:
|
||||
regulator_bulk_free(st->chip_info->num_vrefs, st->vref_reg);
|
||||
error_free_channels:
|
||||
kfree(indio_dev->channels);
|
||||
error_free:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -529,9 +525,6 @@ static int ad5360_remove(struct spi_device *spi)
|
|||
kfree(indio_dev->channels);
|
||||
|
||||
regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg);
|
||||
regulator_bulk_free(st->chip_info->num_vrefs, st->vref_reg);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -369,11 +369,10 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap,
|
|||
unsigned int ctrl = 0;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
dev_err(dev, "Failed to allocate iio device\n");
|
||||
ret = -ENOMEM;
|
||||
goto error_out;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
|
@ -391,13 +390,13 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap,
|
|||
ret = ad5380_alloc_channels(indio_dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to allocate channel spec: %d\n", ret);
|
||||
goto error_free;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (st->chip_info->int_vref == 2500000)
|
||||
ctrl |= AD5380_CTRL_INT_VREF_2V5;
|
||||
|
||||
st->vref_reg = regulator_get(dev, "vref");
|
||||
st->vref_reg = devm_regulator_get(dev, "vref");
|
||||
if (!IS_ERR(st->vref_reg)) {
|
||||
ret = regulator_enable(st->vref_reg);
|
||||
if (ret) {
|
||||
|
@ -434,13 +433,7 @@ error_disable_reg:
|
|||
if (!IS_ERR(st->vref_reg))
|
||||
regulator_disable(st->vref_reg);
|
||||
error_free_reg:
|
||||
if (!IS_ERR(st->vref_reg))
|
||||
regulator_put(st->vref_reg);
|
||||
|
||||
kfree(indio_dev->channels);
|
||||
error_free:
|
||||
iio_device_free(indio_dev);
|
||||
error_out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -456,11 +449,8 @@ static int ad5380_remove(struct device *dev)
|
|||
|
||||
if (!IS_ERR(st->vref_reg)) {
|
||||
regulator_disable(st->vref_reg);
|
||||
regulator_put(st->vref_reg);
|
||||
}
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -451,7 +451,7 @@ static int ad5421_probe(struct spi_device *spi)
|
|||
struct ad5421_state *st;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
dev_err(&spi->dev, "Failed to allocate iio device\n");
|
||||
return -ENOMEM;
|
||||
|
@ -484,31 +484,23 @@ static int ad5421_probe(struct spi_device *spi)
|
|||
ad5421_update_ctrl(indio_dev, 0, 0);
|
||||
|
||||
if (spi->irq) {
|
||||
ret = request_threaded_irq(spi->irq,
|
||||
ret = devm_request_threaded_irq(&spi->dev, spi->irq,
|
||||
NULL,
|
||||
ad5421_fault_handler,
|
||||
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
|
||||
"ad5421 fault",
|
||||
indio_dev);
|
||||
if (ret)
|
||||
goto error_free;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed to register iio device: %d\n", ret);
|
||||
goto error_free_irq;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_free_irq:
|
||||
if (spi->irq)
|
||||
free_irq(spi->irq, indio_dev);
|
||||
error_free:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ad5421_remove(struct spi_device *spi)
|
||||
|
@ -516,9 +508,6 @@ static int ad5421_remove(struct spi_device *spi)
|
|||
struct iio_dev *indio_dev = spi_get_drvdata(spi);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
if (spi->irq)
|
||||
free_irq(spi->irq, indio_dev);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -220,11 +220,11 @@ static int ad5446_probe(struct device *dev, const char *name,
|
|||
struct regulator *reg;
|
||||
int ret, voltage_uv = 0;
|
||||
|
||||
reg = regulator_get(dev, "vcc");
|
||||
reg = devm_regulator_get(dev, "vcc");
|
||||
if (!IS_ERR(reg)) {
|
||||
ret = regulator_enable(reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
return ret;
|
||||
|
||||
ret = regulator_get_voltage(reg);
|
||||
if (ret < 0)
|
||||
|
@ -233,7 +233,7 @@ static int ad5446_probe(struct device *dev, const char *name,
|
|||
voltage_uv = ret;
|
||||
}
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_disable_reg;
|
||||
|
@ -264,19 +264,13 @@ static int ad5446_probe(struct device *dev, const char *name,
|
|||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret)
|
||||
goto error_free_device;
|
||||
goto error_disable_reg;
|
||||
|
||||
return 0;
|
||||
|
||||
error_free_device:
|
||||
iio_device_free(indio_dev);
|
||||
error_disable_reg:
|
||||
if (!IS_ERR(reg))
|
||||
regulator_disable(reg);
|
||||
error_put_reg:
|
||||
if (!IS_ERR(reg))
|
||||
regulator_put(reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -286,11 +280,8 @@ static int ad5446_remove(struct device *dev)
|
|||
struct ad5446_state *st = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
if (!IS_ERR(st->reg)) {
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_disable(st->reg);
|
||||
regulator_put(st->reg);
|
||||
}
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -275,7 +275,7 @@ static int ad5449_spi_probe(struct spi_device *spi)
|
|||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -288,14 +288,14 @@ static int ad5449_spi_probe(struct spi_device *spi)
|
|||
for (i = 0; i < st->chip_info->num_channels; ++i)
|
||||
st->vref_reg[i].supply = ad5449_vref_name(st, i);
|
||||
|
||||
ret = regulator_bulk_get(&spi->dev, st->chip_info->num_channels,
|
||||
ret = devm_regulator_bulk_get(&spi->dev, st->chip_info->num_channels,
|
||||
st->vref_reg);
|
||||
if (ret)
|
||||
goto error_free;
|
||||
return ret;
|
||||
|
||||
ret = regulator_bulk_enable(st->chip_info->num_channels, st->vref_reg);
|
||||
if (ret)
|
||||
goto error_free_reg;
|
||||
return ret;
|
||||
|
||||
indio_dev->dev.parent = &spi->dev;
|
||||
indio_dev->name = id->name;
|
||||
|
@ -325,10 +325,6 @@ static int ad5449_spi_probe(struct spi_device *spi)
|
|||
|
||||
error_disable_reg:
|
||||
regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg);
|
||||
error_free_reg:
|
||||
regulator_bulk_free(st->chip_info->num_channels, st->vref_reg);
|
||||
error_free:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -341,9 +337,6 @@ static int ad5449_spi_remove(struct spi_device *spi)
|
|||
iio_device_unregister(indio_dev);
|
||||
|
||||
regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg);
|
||||
regulator_bulk_free(st->chip_info->num_channels, st->vref_reg);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -281,16 +281,14 @@ static int ad5504_probe(struct spi_device *spi)
|
|||
struct regulator *reg;
|
||||
int ret, voltage_uv = 0;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
reg = regulator_get(&spi->dev, "vcc");
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
reg = devm_regulator_get(&spi->dev, "vcc");
|
||||
if (!IS_ERR(reg)) {
|
||||
ret = regulator_enable(reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
return ret;
|
||||
|
||||
ret = regulator_get_voltage(reg);
|
||||
if (ret < 0)
|
||||
|
@ -321,7 +319,7 @@ static int ad5504_probe(struct spi_device *spi)
|
|||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
if (spi->irq) {
|
||||
ret = request_threaded_irq(spi->irq,
|
||||
ret = devm_request_threaded_irq(&spi->dev, spi->irq,
|
||||
NULL,
|
||||
&ad5504_event_handler,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
|
@ -333,22 +331,14 @@ static int ad5504_probe(struct spi_device *spi)
|
|||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret)
|
||||
goto error_free_irq;
|
||||
goto error_disable_reg;
|
||||
|
||||
return 0;
|
||||
|
||||
error_free_irq:
|
||||
if (spi->irq)
|
||||
free_irq(spi->irq, indio_dev);
|
||||
error_disable_reg:
|
||||
if (!IS_ERR(reg))
|
||||
regulator_disable(reg);
|
||||
error_put_reg:
|
||||
if (!IS_ERR(reg))
|
||||
regulator_put(reg);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -358,14 +348,9 @@ static int ad5504_remove(struct spi_device *spi)
|
|||
struct ad5504_state *st = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
if (spi->irq)
|
||||
free_irq(spi->irq, indio_dev);
|
||||
|
||||
if (!IS_ERR(st->reg)) {
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_disable(st->reg);
|
||||
regulator_put(st->reg);
|
||||
}
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -226,17 +226,15 @@ static int ad5624r_probe(struct spi_device *spi)
|
|||
struct iio_dev *indio_dev;
|
||||
int ret, voltage_uv = 0;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
st = iio_priv(indio_dev);
|
||||
st->reg = regulator_get(&spi->dev, "vcc");
|
||||
st->reg = devm_regulator_get(&spi->dev, "vcc");
|
||||
if (!IS_ERR(st->reg)) {
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
return ret;
|
||||
|
||||
ret = regulator_get_voltage(st->reg);
|
||||
if (ret < 0)
|
||||
|
@ -277,11 +275,6 @@ static int ad5624r_probe(struct spi_device *spi)
|
|||
error_disable_reg:
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_disable(st->reg);
|
||||
error_put_reg:
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_put(st->reg);
|
||||
iio_device_free(indio_dev);
|
||||
error_ret:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -292,11 +285,8 @@ static int ad5624r_remove(struct spi_device *spi)
|
|||
struct ad5624r_state *st = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
if (!IS_ERR(st->reg)) {
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_disable(st->reg);
|
||||
regulator_put(st->reg);
|
||||
}
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -314,18 +314,18 @@ static int ad5686_probe(struct spi_device *spi)
|
|||
struct iio_dev *indio_dev;
|
||||
int ret, regdone = 0, voltage_uv = 0;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
spi_set_drvdata(spi, indio_dev);
|
||||
|
||||
st->reg = regulator_get(&spi->dev, "vcc");
|
||||
st->reg = devm_regulator_get(&spi->dev, "vcc");
|
||||
if (!IS_ERR(st->reg)) {
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
return ret;
|
||||
|
||||
ret = regulator_get_voltage(st->reg);
|
||||
if (ret < 0)
|
||||
|
@ -369,12 +369,6 @@ static int ad5686_probe(struct spi_device *spi)
|
|||
error_disable_reg:
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_disable(st->reg);
|
||||
error_put_reg:
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_put(st->reg);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -384,11 +378,8 @@ static int ad5686_remove(struct spi_device *spi)
|
|||
struct ad5686_state *st = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
if (!IS_ERR(st->reg)) {
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_disable(st->reg);
|
||||
regulator_put(st->reg);
|
||||
}
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -565,7 +565,7 @@ static int ad5755_probe(struct spi_device *spi)
|
|||
struct ad5755_state *st;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
dev_err(&spi->dev, "Failed to allocate iio device\n");
|
||||
return -ENOMEM;
|
||||
|
@ -589,24 +589,19 @@ static int ad5755_probe(struct spi_device *spi)
|
|||
|
||||
ret = ad5755_init_channels(indio_dev, pdata);
|
||||
if (ret)
|
||||
goto error_free;
|
||||
return ret;
|
||||
|
||||
ret = ad5755_setup_pdata(indio_dev, pdata);
|
||||
if (ret)
|
||||
goto error_free;
|
||||
return ret;
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed to register iio device: %d\n", ret);
|
||||
goto error_free;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_free:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ad5755_remove(struct spi_device *spi)
|
||||
|
@ -614,7 +609,6 @@ static int ad5755_remove(struct spi_device *spi)
|
|||
struct iio_dev *indio_dev = spi_get_drvdata(spi);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -275,7 +275,7 @@ static int ad5764_probe(struct spi_device *spi)
|
|||
struct ad5764_state *st;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
dev_err(&spi->dev, "Failed to allocate iio device\n");
|
||||
return -ENOMEM;
|
||||
|
@ -298,12 +298,12 @@ static int ad5764_probe(struct spi_device *spi)
|
|||
st->vref_reg[0].supply = "vrefAB";
|
||||
st->vref_reg[1].supply = "vrefCD";
|
||||
|
||||
ret = regulator_bulk_get(&st->spi->dev,
|
||||
ret = devm_regulator_bulk_get(&st->spi->dev,
|
||||
ARRAY_SIZE(st->vref_reg), st->vref_reg);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed to request vref regulators: %d\n",
|
||||
ret);
|
||||
goto error_free;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(st->vref_reg),
|
||||
|
@ -311,7 +311,7 @@ static int ad5764_probe(struct spi_device *spi)
|
|||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed to enable vref regulators: %d\n",
|
||||
ret);
|
||||
goto error_free_reg;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,12 +326,6 @@ static int ad5764_probe(struct spi_device *spi)
|
|||
error_disable_reg:
|
||||
if (st->chip_info->int_vref == 0)
|
||||
regulator_bulk_disable(ARRAY_SIZE(st->vref_reg), st->vref_reg);
|
||||
error_free_reg:
|
||||
if (st->chip_info->int_vref == 0)
|
||||
regulator_bulk_free(ARRAY_SIZE(st->vref_reg), st->vref_reg);
|
||||
error_free:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -342,12 +336,8 @@ static int ad5764_remove(struct spi_device *spi)
|
|||
|
||||
iio_device_unregister(indio_dev);
|
||||
|
||||
if (st->chip_info->int_vref == 0) {
|
||||
if (st->chip_info->int_vref == 0)
|
||||
regulator_bulk_disable(ARRAY_SIZE(st->vref_reg), st->vref_reg);
|
||||
regulator_bulk_free(ARRAY_SIZE(st->vref_reg), st->vref_reg);
|
||||
}
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -349,17 +349,15 @@ static int ad5791_probe(struct spi_device *spi)
|
|||
struct ad5791_state *st;
|
||||
int ret, pos_voltage_uv = 0, neg_voltage_uv = 0;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
st = iio_priv(indio_dev);
|
||||
st->reg_vdd = regulator_get(&spi->dev, "vdd");
|
||||
st->reg_vdd = devm_regulator_get(&spi->dev, "vdd");
|
||||
if (!IS_ERR(st->reg_vdd)) {
|
||||
ret = regulator_enable(st->reg_vdd);
|
||||
if (ret)
|
||||
goto error_put_reg_pos;
|
||||
return ret;
|
||||
|
||||
ret = regulator_get_voltage(st->reg_vdd);
|
||||
if (ret < 0)
|
||||
|
@ -368,11 +366,11 @@ static int ad5791_probe(struct spi_device *spi)
|
|||
pos_voltage_uv = ret;
|
||||
}
|
||||
|
||||
st->reg_vss = regulator_get(&spi->dev, "vss");
|
||||
st->reg_vss = devm_regulator_get(&spi->dev, "vss");
|
||||
if (!IS_ERR(st->reg_vss)) {
|
||||
ret = regulator_enable(st->reg_vss);
|
||||
if (ret)
|
||||
goto error_put_reg_neg;
|
||||
goto error_disable_reg_pos;
|
||||
|
||||
ret = regulator_get_voltage(st->reg_vss);
|
||||
if (ret < 0)
|
||||
|
@ -428,19 +426,9 @@ static int ad5791_probe(struct spi_device *spi)
|
|||
error_disable_reg_neg:
|
||||
if (!IS_ERR(st->reg_vss))
|
||||
regulator_disable(st->reg_vss);
|
||||
error_put_reg_neg:
|
||||
if (!IS_ERR(st->reg_vss))
|
||||
regulator_put(st->reg_vss);
|
||||
|
||||
error_disable_reg_pos:
|
||||
if (!IS_ERR(st->reg_vdd))
|
||||
regulator_disable(st->reg_vdd);
|
||||
error_put_reg_pos:
|
||||
if (!IS_ERR(st->reg_vdd))
|
||||
regulator_put(st->reg_vdd);
|
||||
iio_device_free(indio_dev);
|
||||
error_ret:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -450,16 +438,11 @@ static int ad5791_remove(struct spi_device *spi)
|
|||
struct ad5791_state *st = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
if (!IS_ERR(st->reg_vdd)) {
|
||||
if (!IS_ERR(st->reg_vdd))
|
||||
regulator_disable(st->reg_vdd);
|
||||
regulator_put(st->reg_vdd);
|
||||
}
|
||||
|
||||
if (!IS_ERR(st->reg_vss)) {
|
||||
if (!IS_ERR(st->reg_vss))
|
||||
regulator_disable(st->reg_vss);
|
||||
regulator_put(st->reg_vss);
|
||||
}
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -203,7 +203,7 @@ static int ad7303_probe(struct spi_device *spi)
|
|||
bool ext_ref;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -212,15 +212,13 @@ static int ad7303_probe(struct spi_device *spi)
|
|||
|
||||
st->spi = spi;
|
||||
|
||||
st->vdd_reg = regulator_get(&spi->dev, "Vdd");
|
||||
if (IS_ERR(st->vdd_reg)) {
|
||||
ret = PTR_ERR(st->vdd_reg);
|
||||
goto err_free;
|
||||
}
|
||||
st->vdd_reg = devm_regulator_get(&spi->dev, "Vdd");
|
||||
if (IS_ERR(st->vdd_reg))
|
||||
return PTR_ERR(st->vdd_reg);
|
||||
|
||||
ret = regulator_enable(st->vdd_reg);
|
||||
if (ret)
|
||||
goto err_put_vdd_reg;
|
||||
return ret;
|
||||
|
||||
if (spi->dev.of_node) {
|
||||
ext_ref = of_property_read_bool(spi->dev.of_node,
|
||||
|
@ -234,7 +232,7 @@ static int ad7303_probe(struct spi_device *spi)
|
|||
}
|
||||
|
||||
if (ext_ref) {
|
||||
st->vref_reg = regulator_get(&spi->dev, "REF");
|
||||
st->vref_reg = devm_regulator_get(&spi->dev, "REF");
|
||||
if (IS_ERR(st->vref_reg)) {
|
||||
ret = PTR_ERR(st->vref_reg);
|
||||
goto err_disable_vdd_reg;
|
||||
|
@ -242,7 +240,7 @@ static int ad7303_probe(struct spi_device *spi)
|
|||
|
||||
ret = regulator_enable(st->vref_reg);
|
||||
if (ret)
|
||||
goto err_put_vref_reg;
|
||||
goto err_disable_vdd_reg;
|
||||
|
||||
st->config |= AD7303_CFG_EXTERNAL_VREF;
|
||||
}
|
||||
|
@ -263,16 +261,8 @@ static int ad7303_probe(struct spi_device *spi)
|
|||
err_disable_vref_reg:
|
||||
if (st->vref_reg)
|
||||
regulator_disable(st->vref_reg);
|
||||
err_put_vref_reg:
|
||||
if (st->vref_reg)
|
||||
regulator_put(st->vref_reg);
|
||||
err_disable_vdd_reg:
|
||||
regulator_disable(st->vdd_reg);
|
||||
err_put_vdd_reg:
|
||||
regulator_put(st->vdd_reg);
|
||||
err_free:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -283,14 +273,9 @@ static int ad7303_remove(struct spi_device *spi)
|
|||
|
||||
iio_device_unregister(indio_dev);
|
||||
|
||||
if (st->vref_reg) {
|
||||
if (st->vref_reg)
|
||||
regulator_disable(st->vref_reg);
|
||||
regulator_put(st->vref_reg);
|
||||
}
|
||||
regulator_disable(st->vdd_reg);
|
||||
regulator_put(st->vdd_reg);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -164,11 +164,9 @@ static int max517_probe(struct i2c_client *client,
|
|||
struct max517_platform_data *platform_data = client->dev.platform_data;
|
||||
int err;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*data));
|
||||
if (indio_dev == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
data = iio_priv(indio_dev);
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
data->client = client;
|
||||
|
@ -198,23 +196,16 @@ static int max517_probe(struct i2c_client *client,
|
|||
|
||||
err = iio_device_register(indio_dev);
|
||||
if (err)
|
||||
goto exit_free_device;
|
||||
return err;
|
||||
|
||||
dev_info(&client->dev, "DAC registered\n");
|
||||
|
||||
return 0;
|
||||
|
||||
exit_free_device:
|
||||
iio_device_free(indio_dev);
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int max517_remove(struct i2c_client *client)
|
||||
{
|
||||
iio_device_unregister(i2c_get_clientdata(client));
|
||||
iio_device_free(i2c_get_clientdata(client));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,14 +12,13 @@
|
|||
* driver for the Microchip I2C 12-bit digital-to-analog converter (DAC)
|
||||
* (7-bit I2C slave address 0x60, the three LSBs can be configured in
|
||||
* hardware)
|
||||
*
|
||||
* writing the DAC value to EEPROM is not supported
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
|
@ -32,15 +31,19 @@ struct mcp4725_data {
|
|||
struct i2c_client *client;
|
||||
u16 vref_mv;
|
||||
u16 dac_value;
|
||||
bool powerdown;
|
||||
unsigned powerdown_mode;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int mcp4725_suspend(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct mcp4725_data *data = iio_priv(indio_dev);
|
||||
u8 outbuf[2];
|
||||
|
||||
outbuf[0] = 0x3 << 4; /* power-down bits, 500 kOhm resistor */
|
||||
outbuf[0] = (data->powerdown_mode + 1) << 4;
|
||||
outbuf[1] = 0;
|
||||
data->powerdown = true;
|
||||
|
||||
return i2c_master_send(to_i2c_client(dev), outbuf, 2);
|
||||
}
|
||||
|
@ -54,16 +57,150 @@ static int mcp4725_resume(struct device *dev)
|
|||
/* restore previous DAC value */
|
||||
outbuf[0] = (data->dac_value >> 8) & 0xf;
|
||||
outbuf[1] = data->dac_value & 0xff;
|
||||
data->powerdown = false;
|
||||
|
||||
return i2c_master_send(to_i2c_client(dev), outbuf, 2);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static SIMPLE_DEV_PM_OPS(mcp4725_pm_ops, mcp4725_suspend, mcp4725_resume);
|
||||
#define MCP4725_PM_OPS (&mcp4725_pm_ops)
|
||||
#else
|
||||
#define MCP4725_PM_OPS NULL
|
||||
#endif
|
||||
|
||||
static ssize_t mcp4725_store_eeprom(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t len)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct mcp4725_data *data = iio_priv(indio_dev);
|
||||
int tries = 20;
|
||||
u8 inoutbuf[3];
|
||||
bool state;
|
||||
int ret;
|
||||
|
||||
ret = strtobool(buf, &state);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!state)
|
||||
return 0;
|
||||
|
||||
inoutbuf[0] = 0x60; /* write EEPROM */
|
||||
inoutbuf[1] = data->dac_value >> 4;
|
||||
inoutbuf[2] = (data->dac_value & 0xf) << 4;
|
||||
|
||||
ret = i2c_master_send(data->client, inoutbuf, 3);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (ret != 3)
|
||||
return -EIO;
|
||||
|
||||
/* wait for write complete, takes up to 50ms */
|
||||
while (tries--) {
|
||||
msleep(20);
|
||||
ret = i2c_master_recv(data->client, inoutbuf, 3);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (ret != 3)
|
||||
return -EIO;
|
||||
|
||||
if (inoutbuf[0] & 0x80)
|
||||
break;
|
||||
}
|
||||
|
||||
if (tries < 0) {
|
||||
dev_err(&data->client->dev,
|
||||
"mcp4725_store_eeprom() failed, incomplete\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(store_eeprom, S_IWUSR, NULL, mcp4725_store_eeprom, 0);
|
||||
|
||||
static struct attribute *mcp4725_attributes[] = {
|
||||
&iio_dev_attr_store_eeprom.dev_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group mcp4725_attribute_group = {
|
||||
.attrs = mcp4725_attributes,
|
||||
};
|
||||
|
||||
static const char * const mcp4725_powerdown_modes[] = {
|
||||
"1kohm_to_gnd",
|
||||
"100kohm_to_gnd",
|
||||
"500kohm_to_gnd"
|
||||
};
|
||||
|
||||
static int mcp4725_get_powerdown_mode(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan)
|
||||
{
|
||||
struct mcp4725_data *data = iio_priv(indio_dev);
|
||||
|
||||
return data->powerdown_mode;
|
||||
}
|
||||
|
||||
static int mcp4725_set_powerdown_mode(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan, unsigned mode)
|
||||
{
|
||||
struct mcp4725_data *data = iio_priv(indio_dev);
|
||||
|
||||
data->powerdown_mode = mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t mcp4725_read_powerdown(struct iio_dev *indio_dev,
|
||||
uintptr_t private, const struct iio_chan_spec *chan, char *buf)
|
||||
{
|
||||
struct mcp4725_data *data = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", data->powerdown);
|
||||
}
|
||||
|
||||
static ssize_t mcp4725_write_powerdown(struct iio_dev *indio_dev,
|
||||
uintptr_t private, const struct iio_chan_spec *chan,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct mcp4725_data *data = iio_priv(indio_dev);
|
||||
bool state;
|
||||
int ret;
|
||||
|
||||
ret = strtobool(buf, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (state)
|
||||
ret = mcp4725_suspend(&data->client->dev);
|
||||
else
|
||||
ret = mcp4725_resume(&data->client->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct iio_enum mcp4725_powerdown_mode_enum = {
|
||||
.items = mcp4725_powerdown_modes,
|
||||
.num_items = ARRAY_SIZE(mcp4725_powerdown_modes),
|
||||
.get = mcp4725_get_powerdown_mode,
|
||||
.set = mcp4725_set_powerdown_mode,
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = {
|
||||
{
|
||||
.name = "powerdown",
|
||||
.read = mcp4725_read_powerdown,
|
||||
.write = mcp4725_write_powerdown,
|
||||
},
|
||||
IIO_ENUM("powerdown_mode", false, &mcp4725_powerdown_mode_enum),
|
||||
IIO_ENUM_AVAILABLE("powerdown_mode", &mcp4725_powerdown_mode_enum),
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec mcp4725_channel = {
|
||||
.type = IIO_VOLTAGE,
|
||||
.indexed = 1,
|
||||
|
@ -72,6 +209,7 @@ static const struct iio_chan_spec mcp4725_channel = {
|
|||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
|
||||
.scan_type = IIO_ST('u', 12, 16, 0),
|
||||
.ext_info = mcp4725_ext_info,
|
||||
};
|
||||
|
||||
static int mcp4725_set_value(struct iio_dev *indio_dev, int val)
|
||||
|
@ -138,6 +276,7 @@ static int mcp4725_write_raw(struct iio_dev *indio_dev,
|
|||
static const struct iio_info mcp4725_info = {
|
||||
.read_raw = mcp4725_read_raw,
|
||||
.write_raw = mcp4725_write_raw,
|
||||
.attrs = &mcp4725_attribute_group,
|
||||
.driver_module = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@ -148,19 +287,17 @@ static int mcp4725_probe(struct i2c_client *client,
|
|||
struct iio_dev *indio_dev;
|
||||
struct mcp4725_platform_data *platform_data = client->dev.platform_data;
|
||||
u8 inbuf[3];
|
||||
u8 pd;
|
||||
int err;
|
||||
|
||||
if (!platform_data || !platform_data->vref_mv) {
|
||||
dev_err(&client->dev, "invalid platform data");
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*data));
|
||||
if (indio_dev == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
data = iio_priv(indio_dev);
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
data->client = client;
|
||||
|
@ -177,31 +314,25 @@ static int mcp4725_probe(struct i2c_client *client,
|
|||
err = i2c_master_recv(client, inbuf, 3);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "failed to read DAC value");
|
||||
goto exit_free_device;
|
||||
return err;
|
||||
}
|
||||
pd = (inbuf[0] >> 1) & 0x3;
|
||||
data->powerdown = pd > 0 ? true : false;
|
||||
data->powerdown_mode = pd ? pd-1 : 2; /* 500kohm_to_gnd */
|
||||
data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
|
||||
|
||||
err = iio_device_register(indio_dev);
|
||||
if (err)
|
||||
goto exit_free_device;
|
||||
return err;
|
||||
|
||||
dev_info(&client->dev, "MCP4725 DAC registered\n");
|
||||
|
||||
return 0;
|
||||
|
||||
exit_free_device:
|
||||
iio_device_free(indio_dev);
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mcp4725_remove(struct i2c_client *client)
|
||||
{
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
iio_device_unregister(i2c_get_clientdata(client));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
# Clock Distribution device drivers
|
||||
# Phase-Locked Loop (PLL) frequency synthesizers
|
||||
#
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
|
||||
menu "Frequency Synthesizers DDS/PLL"
|
||||
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
# Makefile iio/frequency
|
||||
#
|
||||
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
obj-$(CONFIG_AD9523) += ad9523.o
|
||||
obj-$(CONFIG_ADF4350) += adf4350.o
|
||||
|
|
|
@ -961,17 +961,17 @@ static int ad9523_probe(struct spi_device *spi)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
st->reg = regulator_get(&spi->dev, "vcc");
|
||||
st->reg = devm_regulator_get(&spi->dev, "vcc");
|
||||
if (!IS_ERR(st->reg)) {
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
return ret;
|
||||
}
|
||||
|
||||
spi_set_drvdata(spi, indio_dev);
|
||||
|
@ -1001,11 +1001,6 @@ static int ad9523_probe(struct spi_device *spi)
|
|||
error_disable_reg:
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_disable(st->reg);
|
||||
error_put_reg:
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_put(st->reg);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1017,12 +1012,8 @@ static int ad9523_remove(struct spi_device *spi)
|
|||
|
||||
iio_device_unregister(indio_dev);
|
||||
|
||||
if (!IS_ERR(st->reg)) {
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_disable(st->reg);
|
||||
regulator_put(st->reg);
|
||||
}
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -515,7 +515,7 @@ static int adf4350_probe(struct spi_device *spi)
|
|||
}
|
||||
|
||||
if (!pdata->clkin) {
|
||||
clk = clk_get(&spi->dev, "clkin");
|
||||
clk = devm_clk_get(&spi->dev, "clkin");
|
||||
if (IS_ERR(clk))
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
|
@ -524,17 +524,17 @@ static int adf4350_probe(struct spi_device *spi)
|
|||
return ret;
|
||||
}
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
st->reg = regulator_get(&spi->dev, "vcc");
|
||||
st->reg = devm_regulator_get(&spi->dev, "vcc");
|
||||
if (!IS_ERR(st->reg)) {
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
goto error_disable_clk;
|
||||
}
|
||||
|
||||
spi_set_drvdata(spi, indio_dev);
|
||||
|
@ -564,7 +564,8 @@ static int adf4350_probe(struct spi_device *spi)
|
|||
memset(st->regs_hw, 0xFF, sizeof(st->regs_hw));
|
||||
|
||||
if (gpio_is_valid(pdata->gpio_lock_detect)) {
|
||||
ret = gpio_request(pdata->gpio_lock_detect, indio_dev->name);
|
||||
ret = devm_gpio_request(&spi->dev, pdata->gpio_lock_detect,
|
||||
indio_dev->name);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "fail to request lock detect GPIO-%d",
|
||||
pdata->gpio_lock_detect);
|
||||
|
@ -576,29 +577,21 @@ static int adf4350_probe(struct spi_device *spi)
|
|||
if (pdata->power_up_frequency) {
|
||||
ret = adf4350_set_freq(st, pdata->power_up_frequency);
|
||||
if (ret)
|
||||
goto error_free_gpio;
|
||||
goto error_disable_reg;
|
||||
}
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret)
|
||||
goto error_free_gpio;
|
||||
goto error_disable_reg;
|
||||
|
||||
return 0;
|
||||
|
||||
error_free_gpio:
|
||||
if (gpio_is_valid(pdata->gpio_lock_detect))
|
||||
gpio_free(pdata->gpio_lock_detect);
|
||||
|
||||
error_disable_reg:
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_disable(st->reg);
|
||||
error_put_reg:
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_put(st->reg);
|
||||
|
||||
error_disable_clk:
|
||||
if (clk)
|
||||
clk_disable_unprepare(clk);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -619,14 +612,8 @@ static int adf4350_remove(struct spi_device *spi)
|
|||
|
||||
if (!IS_ERR(reg)) {
|
||||
regulator_disable(reg);
|
||||
regulator_put(reg);
|
||||
}
|
||||
|
||||
if (gpio_is_valid(st->pdata->gpio_lock_detect))
|
||||
gpio_free(st->pdata->gpio_lock_detect);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# IIO Digital Gyroscope Sensor drivers configuration
|
||||
#
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
|
||||
menu "Digital gyroscope sensors"
|
||||
|
||||
config ADIS16080
|
||||
|
@ -26,6 +28,18 @@ config ADIS16136
|
|||
Say yes here to build support for the Analog Devices ADIS16133, ADIS16135,
|
||||
ADIS16136 gyroscope devices.
|
||||
|
||||
config ADIS16260
|
||||
tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver"
|
||||
depends on SPI
|
||||
select IIO_ADIS_LIB
|
||||
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
|
||||
help
|
||||
Say yes here to build support for Analog Devices ADIS16260 ADIS16265
|
||||
ADIS16250 ADIS16255 and ADIS16251 programmable digital gyroscope sensors.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called adis16260.
|
||||
|
||||
config ADXRS450
|
||||
tristate "Analog Devices ADXRS450/3 Digital Output Gyroscope SPI driver"
|
||||
depends on SPI
|
||||
|
@ -58,8 +72,8 @@ config IIO_ST_GYRO_3AXIS
|
|||
Say yes here to build support for STMicroelectronics gyroscopes:
|
||||
L3G4200D, LSM330DL, L3GD20, L3GD20H, LSM330DLC, L3G4IS, LSM330.
|
||||
|
||||
This driver can also be built as a module. If so, will be created
|
||||
these modules:
|
||||
This driver can also be built as a module. If so, these modules
|
||||
will be created:
|
||||
- st_gyro (core functions for the driver [it is mandatory]);
|
||||
- st_gyro_i2c (necessary for the I2C devices [optional*]);
|
||||
- st_gyro_spi (necessary for the SPI devices [optional*]);
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
# Makefile for industrial I/O gyroscope sensor drivers
|
||||
#
|
||||
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
obj-$(CONFIG_ADIS16080) += adis16080.o
|
||||
obj-$(CONFIG_ADIS16130) += adis16130.o
|
||||
obj-$(CONFIG_ADIS16136) += adis16136.o
|
||||
obj-$(CONFIG_ADIS16260) += adis16260.o
|
||||
obj-$(CONFIG_ADXRS450) += adxrs450.o
|
||||
|
||||
obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o
|
||||
|
|
|
@ -192,16 +192,13 @@ static const struct adis16080_chip_info adis16080_chip_info[] = {
|
|||
static int adis16080_probe(struct spi_device *spi)
|
||||
{
|
||||
const struct spi_device_id *id = spi_get_device_id(spi);
|
||||
int ret;
|
||||
struct adis16080_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
|
||||
/* setup the industrialio driver allocated elements */
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
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);
|
||||
|
@ -217,22 +214,12 @@ static int adis16080_probe(struct spi_device *spi)
|
|||
indio_dev->info = &adis16080_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret)
|
||||
goto error_free_dev;
|
||||
return 0;
|
||||
|
||||
error_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
error_ret:
|
||||
return ret;
|
||||
return iio_device_register(indio_dev);
|
||||
}
|
||||
|
||||
static int adis16080_remove(struct spi_device *spi)
|
||||
{
|
||||
iio_device_unregister(spi_get_drvdata(spi));
|
||||
iio_device_free(spi_get_drvdata(spi));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -148,16 +148,13 @@ static const struct iio_info adis16130_info = {
|
|||
|
||||
static int adis16130_probe(struct spi_device *spi)
|
||||
{
|
||||
int ret;
|
||||
struct adis16130_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
|
||||
/* setup the industrialio driver allocated elements */
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
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);
|
||||
|
@ -170,24 +167,12 @@ static int adis16130_probe(struct spi_device *spi)
|
|||
indio_dev->info = &adis16130_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret)
|
||||
goto error_free_dev;
|
||||
|
||||
return 0;
|
||||
|
||||
error_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
error_ret:
|
||||
return ret;
|
||||
return iio_device_register(indio_dev);
|
||||
}
|
||||
|
||||
static int adis16130_remove(struct spi_device *spi)
|
||||
{
|
||||
iio_device_unregister(spi_get_drvdata(spi));
|
||||
iio_device_free(spi_get_drvdata(spi));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -497,7 +497,7 @@ static int adis16136_probe(struct spi_device *spi)
|
|||
struct iio_dev *indio_dev;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*adis16136));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis16136));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -515,11 +515,11 @@ static int adis16136_probe(struct spi_device *spi)
|
|||
|
||||
ret = adis_init(&adis16136->adis, indio_dev, spi, &adis16136_data);
|
||||
if (ret)
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
|
||||
ret = adis_setup_buffer_and_trigger(&adis16136->adis, indio_dev, NULL);
|
||||
if (ret)
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
|
||||
ret = adis16136_initial_setup(indio_dev);
|
||||
if (ret)
|
||||
|
@ -537,8 +537,6 @@ error_stop_device:
|
|||
adis16136_stop_device(indio_dev);
|
||||
error_cleanup_buffer:
|
||||
adis_cleanup_buffer_and_trigger(&adis16136->adis, indio_dev);
|
||||
error_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -552,8 +550,6 @@ static int adis16136_remove(struct spi_device *spi)
|
|||
|
||||
adis_cleanup_buffer_and_trigger(&adis16136->adis, indio_dev);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,54 +7,119 @@
|
|||
*/
|
||||
|
||||
#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 "adis16260.h"
|
||||
#define ADIS16260_STARTUP_DELAY 220 /* ms */
|
||||
|
||||
static ssize_t adis16260_read_frequency_available(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct adis16260_state *st = iio_priv(indio_dev);
|
||||
if (spi_get_device_id(st->adis.spi)->driver_data)
|
||||
return sprintf(buf, "%s\n", "0.129 ~ 256");
|
||||
else
|
||||
return sprintf(buf, "%s\n", "256 2048");
|
||||
}
|
||||
#define ADIS16260_FLASH_CNT 0x00 /* Flash memory write count */
|
||||
#define ADIS16260_SUPPLY_OUT 0x02 /* Power supply measurement */
|
||||
#define ADIS16260_GYRO_OUT 0x04 /* X-axis gyroscope output */
|
||||
#define ADIS16260_AUX_ADC 0x0A /* analog input channel measurement */
|
||||
#define ADIS16260_TEMP_OUT 0x0C /* internal temperature measurement */
|
||||
#define ADIS16260_ANGL_OUT 0x0E /* angle displacement */
|
||||
#define ADIS16260_GYRO_OFF 0x14 /* Calibration, offset/bias adjustment */
|
||||
#define ADIS16260_GYRO_SCALE 0x16 /* Calibration, scale adjustment */
|
||||
#define ADIS16260_ALM_MAG1 0x20 /* Alarm 1 magnitude/polarity setting */
|
||||
#define ADIS16260_ALM_MAG2 0x22 /* Alarm 2 magnitude/polarity setting */
|
||||
#define ADIS16260_ALM_SMPL1 0x24 /* Alarm 1 dynamic rate of change setting */
|
||||
#define ADIS16260_ALM_SMPL2 0x26 /* Alarm 2 dynamic rate of change setting */
|
||||
#define ADIS16260_ALM_CTRL 0x28 /* Alarm control */
|
||||
#define ADIS16260_AUX_DAC 0x30 /* Auxiliary DAC data */
|
||||
#define ADIS16260_GPIO_CTRL 0x32 /* Control, digital I/O line */
|
||||
#define ADIS16260_MSC_CTRL 0x34 /* Control, data ready, self-test settings */
|
||||
#define ADIS16260_SMPL_PRD 0x36 /* Control, internal sample rate */
|
||||
#define ADIS16260_SENS_AVG 0x38 /* Control, dynamic range, filtering */
|
||||
#define ADIS16260_SLP_CNT 0x3A /* Control, sleep mode initiation */
|
||||
#define ADIS16260_DIAG_STAT 0x3C /* Diagnostic, error flags */
|
||||
#define ADIS16260_GLOB_CMD 0x3E /* Control, global commands */
|
||||
#define ADIS16260_LOT_ID1 0x52 /* Lot Identification Code 1 */
|
||||
#define ADIS16260_LOT_ID2 0x54 /* Lot Identification Code 2 */
|
||||
#define ADIS16260_PROD_ID 0x56 /* Product identifier;
|
||||
* convert to decimal = 16,265/16,260 */
|
||||
#define ADIS16260_SERIAL_NUM 0x58 /* Serial number */
|
||||
|
||||
#define ADIS16260_ERROR_ACTIVE (1<<14)
|
||||
#define ADIS16260_NEW_DATA (1<<15)
|
||||
|
||||
/* MSC_CTRL */
|
||||
#define ADIS16260_MSC_CTRL_MEM_TEST (1<<11)
|
||||
/* Internal self-test enable */
|
||||
#define ADIS16260_MSC_CTRL_INT_SELF_TEST (1<<10)
|
||||
#define ADIS16260_MSC_CTRL_NEG_SELF_TEST (1<<9)
|
||||
#define ADIS16260_MSC_CTRL_POS_SELF_TEST (1<<8)
|
||||
#define ADIS16260_MSC_CTRL_DATA_RDY_EN (1<<2)
|
||||
#define ADIS16260_MSC_CTRL_DATA_RDY_POL_HIGH (1<<1)
|
||||
#define ADIS16260_MSC_CTRL_DATA_RDY_DIO2 (1<<0)
|
||||
|
||||
/* SMPL_PRD */
|
||||
/* Time base (tB): 0 = 1.953 ms, 1 = 60.54 ms */
|
||||
#define ADIS16260_SMPL_PRD_TIME_BASE (1<<7)
|
||||
#define ADIS16260_SMPL_PRD_DIV_MASK 0x7F
|
||||
|
||||
/* SLP_CNT */
|
||||
#define ADIS16260_SLP_CNT_POWER_OFF 0x80
|
||||
|
||||
/* DIAG_STAT */
|
||||
#define ADIS16260_DIAG_STAT_ALARM2 (1<<9)
|
||||
#define ADIS16260_DIAG_STAT_ALARM1 (1<<8)
|
||||
#define ADIS16260_DIAG_STAT_FLASH_CHK_BIT 6
|
||||
#define ADIS16260_DIAG_STAT_SELF_TEST_BIT 5
|
||||
#define ADIS16260_DIAG_STAT_OVERFLOW_BIT 4
|
||||
#define ADIS16260_DIAG_STAT_SPI_FAIL_BIT 3
|
||||
#define ADIS16260_DIAG_STAT_FLASH_UPT_BIT 2
|
||||
#define ADIS16260_DIAG_STAT_POWER_HIGH_BIT 1
|
||||
#define ADIS16260_DIAG_STAT_POWER_LOW_BIT 0
|
||||
|
||||
/* GLOB_CMD */
|
||||
#define ADIS16260_GLOB_CMD_SW_RESET (1<<7)
|
||||
#define ADIS16260_GLOB_CMD_FLASH_UPD (1<<3)
|
||||
#define ADIS16260_GLOB_CMD_DAC_LATCH (1<<2)
|
||||
#define ADIS16260_GLOB_CMD_FAC_CALIB (1<<1)
|
||||
#define ADIS16260_GLOB_CMD_AUTO_NULL (1<<0)
|
||||
|
||||
#define ADIS16260_SPI_SLOW (u32)(300 * 1000)
|
||||
#define ADIS16260_SPI_BURST (u32)(1000 * 1000)
|
||||
#define ADIS16260_SPI_FAST (u32)(2000 * 1000)
|
||||
|
||||
/* At the moment triggers are only used for ring buffer
|
||||
* filling. This may change!
|
||||
*/
|
||||
|
||||
#define ADIS16260_SCAN_GYRO 0
|
||||
#define ADIS16260_SCAN_SUPPLY 1
|
||||
#define ADIS16260_SCAN_AUX_ADC 2
|
||||
#define ADIS16260_SCAN_TEMP 3
|
||||
#define ADIS16260_SCAN_ANGL 4
|
||||
|
||||
static ssize_t adis16260_read_frequency(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct adis16260_state *st = iio_priv(indio_dev);
|
||||
struct adis *adis = iio_priv(indio_dev);
|
||||
int ret, len = 0;
|
||||
u16 t;
|
||||
int sps;
|
||||
ret = adis_read_reg_16(&st->adis, ADIS16260_SMPL_PRD, &t);
|
||||
ret = adis_read_reg_16(adis, ADIS16260_SMPL_PRD, &t);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (spi_get_device_id(st->adis.spi)->driver_data) /* If an adis16251 */
|
||||
sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 8 : 256;
|
||||
if (spi_get_device_id(adis->spi)->driver_data) /* If an adis16251 */
|
||||
sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 8 : 256;
|
||||
else
|
||||
sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048;
|
||||
sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048;
|
||||
sps /= (t & ADIS16260_SMPL_PRD_DIV_MASK) + 1;
|
||||
len = sprintf(buf, "%d SPS\n", sps);
|
||||
len = sprintf(buf, "%d\n", sps);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -64,36 +129,31 @@ static ssize_t adis16260_write_frequency(struct device *dev,
|
|||
size_t len)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct adis16260_state *st = iio_priv(indio_dev);
|
||||
long val;
|
||||
struct adis *adis = iio_priv(indio_dev);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
u8 t;
|
||||
|
||||
ret = strict_strtol(buf, 10, &val);
|
||||
ret = kstrtouint(buf, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (val == 0)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
if (spi_get_device_id(st->adis.spi)->driver_data) {
|
||||
t = (256 / val);
|
||||
if (t > 0)
|
||||
t--;
|
||||
t &= ADIS16260_SMPL_PRD_DIV_MASK;
|
||||
} else {
|
||||
t = (2048 / val);
|
||||
if (t > 0)
|
||||
t--;
|
||||
t &= ADIS16260_SMPL_PRD_DIV_MASK;
|
||||
}
|
||||
if ((t & ADIS16260_SMPL_PRD_DIV_MASK) >= 0x0A)
|
||||
st->adis.spi->max_speed_hz = ADIS16260_SPI_SLOW;
|
||||
if (spi_get_device_id(adis->spi)->driver_data)
|
||||
t = 256 / val;
|
||||
else
|
||||
st->adis.spi->max_speed_hz = ADIS16260_SPI_FAST;
|
||||
ret = adis_write_reg_8(&st->adis,
|
||||
ADIS16260_SMPL_PRD,
|
||||
t);
|
||||
t = 2048 / val;
|
||||
|
||||
if (t > ADIS16260_SMPL_PRD_DIV_MASK)
|
||||
t = ADIS16260_SMPL_PRD_DIV_MASK;
|
||||
else if (t > 0)
|
||||
t--;
|
||||
|
||||
if (t >= 0x0A)
|
||||
adis->spi->max_speed_hz = ADIS16260_SPI_SLOW;
|
||||
else
|
||||
adis->spi->max_speed_hz = ADIS16260_SPI_FAST;
|
||||
ret = adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t);
|
||||
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
|
||||
|
@ -103,11 +163,11 @@ static ssize_t adis16260_write_frequency(struct device *dev,
|
|||
/* Power down the device */
|
||||
static int adis16260_stop_device(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct adis16260_state *st = iio_priv(indio_dev);
|
||||
struct adis *adis = iio_priv(indio_dev);
|
||||
int ret;
|
||||
u16 val = ADIS16260_SLP_CNT_POWER_OFF;
|
||||
|
||||
ret = adis_write_reg_16(&st->adis, ADIS16260_SLP_CNT, val);
|
||||
ret = adis_write_reg_16(adis, ADIS16260_SLP_CNT, val);
|
||||
if (ret)
|
||||
dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
|
||||
|
||||
|
@ -118,24 +178,16 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
|
|||
adis16260_read_frequency,
|
||||
adis16260_write_frequency);
|
||||
|
||||
static IIO_DEVICE_ATTR(sampling_frequency_available,
|
||||
S_IRUGO, adis16260_read_frequency_available, NULL, 0);
|
||||
|
||||
#define ADIS16260_GYRO_CHANNEL_SET(axis, mod) \
|
||||
struct iio_chan_spec adis16260_channels_##axis[] = { \
|
||||
ADIS_GYRO_CHAN(mod, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO, \
|
||||
BIT(IIO_CHAN_INFO_CALIBBIAS) | \
|
||||
BIT(IIO_CHAN_INFO_CALIBSCALE), 14), \
|
||||
ADIS_INCLI_CHAN(mod, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0, 14), \
|
||||
ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP, 12), \
|
||||
ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY, 12), \
|
||||
ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC, 12), \
|
||||
IIO_CHAN_SOFT_TIMESTAMP(5), \
|
||||
}
|
||||
|
||||
static const ADIS16260_GYRO_CHANNEL_SET(x, X);
|
||||
static const ADIS16260_GYRO_CHANNEL_SET(y, Y);
|
||||
static const ADIS16260_GYRO_CHANNEL_SET(z, Z);
|
||||
static const struct iio_chan_spec adis16260_channels[] = {
|
||||
ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
|
||||
BIT(IIO_CHAN_INFO_CALIBBIAS) |
|
||||
BIT(IIO_CHAN_INFO_CALIBSCALE), 14),
|
||||
ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0, 14),
|
||||
ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP, 12),
|
||||
ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY, 12),
|
||||
ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC, 12),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(5),
|
||||
};
|
||||
|
||||
static const u8 adis16260_addresses[][2] = {
|
||||
[ADIS16260_SCAN_GYRO] = { ADIS16260_GYRO_OFF, ADIS16260_GYRO_SCALE },
|
||||
|
@ -146,9 +198,8 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
|
|||
int *val, int *val2,
|
||||
long mask)
|
||||
{
|
||||
struct adis16260_state *st = iio_priv(indio_dev);
|
||||
struct adis *adis = iio_priv(indio_dev);
|
||||
int ret;
|
||||
int bits;
|
||||
u8 addr;
|
||||
s16 val16;
|
||||
|
||||
|
@ -160,7 +211,7 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
|
|||
switch (chan->type) {
|
||||
case IIO_ANGL_VEL:
|
||||
*val = 0;
|
||||
if (spi_get_device_id(st->adis.spi)->driver_data) {
|
||||
if (spi_get_device_id(adis->spi)->driver_data) {
|
||||
/* 0.01832 degree / sec */
|
||||
*val2 = IIO_DEGREE_TO_RAD(18320);
|
||||
} else {
|
||||
|
@ -168,6 +219,10 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
|
|||
*val2 = IIO_DEGREE_TO_RAD(73260);
|
||||
}
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
case IIO_INCLI:
|
||||
*val = 0;
|
||||
*val2 = IIO_DEGREE_TO_RAD(36630);
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
case IIO_VOLTAGE:
|
||||
if (chan->channel == 0) {
|
||||
*val = 1;
|
||||
|
@ -189,42 +244,20 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
|
|||
*val = 250000 / 1453; /* 25 C = 0x00 */
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_CALIBBIAS:
|
||||
switch (chan->type) {
|
||||
case IIO_ANGL_VEL:
|
||||
bits = 12;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
addr = adis16260_addresses[chan->scan_index][0];
|
||||
ret = adis_read_reg_16(&st->adis, addr, &val16);
|
||||
if (ret) {
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
ret = adis_read_reg_16(adis, addr, &val16);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
val16 &= (1 << bits) - 1;
|
||||
val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
|
||||
*val = val16;
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
|
||||
*val = sign_extend32(val16, 11);
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_CALIBSCALE:
|
||||
switch (chan->type) {
|
||||
case IIO_ANGL_VEL:
|
||||
bits = 12;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
addr = adis16260_addresses[chan->scan_index][1];
|
||||
ret = adis_read_reg_16(&st->adis, addr, &val16);
|
||||
if (ret) {
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
ret = adis_read_reg_16(adis, addr, &val16);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
*val = (1 << bits) - 1;
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
|
||||
*val = val16;
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
return -EINVAL;
|
||||
|
@ -236,26 +269,28 @@ static int adis16260_write_raw(struct iio_dev *indio_dev,
|
|||
int val2,
|
||||
long mask)
|
||||
{
|
||||
struct adis16260_state *st = iio_priv(indio_dev);
|
||||
int bits = 12;
|
||||
s16 val16;
|
||||
struct adis *adis = iio_priv(indio_dev);
|
||||
u8 addr;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_CALIBBIAS:
|
||||
val16 = val & ((1 << bits) - 1);
|
||||
if (val < -2048 || val >= 2048)
|
||||
return -EINVAL;
|
||||
|
||||
addr = adis16260_addresses[chan->scan_index][0];
|
||||
return adis_write_reg_16(&st->adis, addr, val16);
|
||||
return adis_write_reg_16(adis, addr, val);
|
||||
case IIO_CHAN_INFO_CALIBSCALE:
|
||||
val16 = val & ((1 << bits) - 1);
|
||||
if (val < 0 || val >= 4096)
|
||||
return -EINVAL;
|
||||
|
||||
addr = adis16260_addresses[chan->scan_index][1];
|
||||
return adis_write_reg_16(&st->adis, addr, val16);
|
||||
return adis_write_reg_16(adis, addr, val);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct attribute *adis16260_attributes[] = {
|
||||
&iio_dev_attr_sampling_frequency.dev_attr.attr,
|
||||
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -303,71 +338,35 @@ static const struct adis_data adis16260_data = {
|
|||
|
||||
static int adis16260_probe(struct spi_device *spi)
|
||||
{
|
||||
int ret;
|
||||
struct adis16260_platform_data *pd = spi->dev.platform_data;
|
||||
struct adis16260_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
struct adis *adis;
|
||||
int ret;
|
||||
|
||||
/* setup the industrialio driver allocated elements */
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
st = iio_priv(indio_dev);
|
||||
if (pd)
|
||||
st->negate = pd->negate;
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
adis = iio_priv(indio_dev);
|
||||
/* this is only used for removal purposes */
|
||||
spi_set_drvdata(spi, indio_dev);
|
||||
|
||||
indio_dev->name = spi_get_device_id(spi)->name;
|
||||
indio_dev->dev.parent = &spi->dev;
|
||||
indio_dev->info = &adis16260_info;
|
||||
indio_dev->num_channels
|
||||
= ARRAY_SIZE(adis16260_channels_x);
|
||||
if (pd && pd->direction)
|
||||
switch (pd->direction) {
|
||||
case 'x':
|
||||
indio_dev->channels = adis16260_channels_x;
|
||||
break;
|
||||
case 'y':
|
||||
indio_dev->channels = adis16260_channels_y;
|
||||
break;
|
||||
case 'z':
|
||||
indio_dev->channels = adis16260_channels_z;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
else
|
||||
indio_dev->channels = adis16260_channels_x;
|
||||
indio_dev->num_channels = ARRAY_SIZE(adis16260_channels_x);
|
||||
indio_dev->channels = adis16260_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(adis16260_channels);
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
ret = adis_init(&st->adis, indio_dev, spi, &adis16260_data);
|
||||
ret = adis_init(adis, indio_dev, spi, &adis16260_data);
|
||||
if (ret)
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
|
||||
ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL);
|
||||
ret = adis_setup_buffer_and_trigger(adis, indio_dev, NULL);
|
||||
if (ret)
|
||||
goto error_free_dev;
|
||||
|
||||
if (indio_dev->buffer) {
|
||||
/* Set default scan mode */
|
||||
iio_scan_mask_set(indio_dev, indio_dev->buffer,
|
||||
ADIS16260_SCAN_SUPPLY);
|
||||
iio_scan_mask_set(indio_dev, indio_dev->buffer,
|
||||
ADIS16260_SCAN_GYRO);
|
||||
iio_scan_mask_set(indio_dev, indio_dev->buffer,
|
||||
ADIS16260_SCAN_AUX_ADC);
|
||||
iio_scan_mask_set(indio_dev, indio_dev->buffer,
|
||||
ADIS16260_SCAN_TEMP);
|
||||
iio_scan_mask_set(indio_dev, indio_dev->buffer,
|
||||
ADIS16260_SCAN_ANGL);
|
||||
}
|
||||
return ret;
|
||||
|
||||
/* Get the device into a sane initial state */
|
||||
ret = adis_initial_startup(&st->adis);
|
||||
ret = adis_initial_startup(adis);
|
||||
if (ret)
|
||||
goto error_cleanup_buffer_trigger;
|
||||
ret = iio_device_register(indio_dev);
|
||||
|
@ -377,22 +376,18 @@ static int adis16260_probe(struct spi_device *spi)
|
|||
return 0;
|
||||
|
||||
error_cleanup_buffer_trigger:
|
||||
adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
|
||||
error_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
error_ret:
|
||||
adis_cleanup_buffer_and_trigger(adis, indio_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adis16260_remove(struct spi_device *spi)
|
||||
{
|
||||
struct iio_dev *indio_dev = spi_get_drvdata(spi);
|
||||
struct adis16260_state *st = iio_priv(indio_dev);
|
||||
struct adis *adis = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
adis16260_stop_device(indio_dev);
|
||||
adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
|
||||
iio_device_free(indio_dev);
|
||||
adis_cleanup_buffer_and_trigger(adis, indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -426,11 +426,9 @@ static int adxrs450_probe(struct spi_device *spi)
|
|||
struct iio_dev *indio_dev;
|
||||
|
||||
/* setup the industrialio driver allocated elements */
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
st = iio_priv(indio_dev);
|
||||
st->us = spi;
|
||||
mutex_init(&st->buf_lock);
|
||||
|
@ -447,7 +445,7 @@ static int adxrs450_probe(struct spi_device *spi)
|
|||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret)
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
|
||||
/* Get the device into a sane initial state */
|
||||
ret = adxrs450_initial_setup(indio_dev);
|
||||
|
@ -456,17 +454,12 @@ static int adxrs450_probe(struct spi_device *spi)
|
|||
return 0;
|
||||
error_initial:
|
||||
iio_device_unregister(indio_dev);
|
||||
error_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adxrs450_remove(struct spi_device *spi)
|
||||
{
|
||||
iio_device_unregister(spi_get_drvdata(spi));
|
||||
iio_device_free(spi_get_drvdata(spi));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -30,10 +30,6 @@
|
|||
#include <linux/iio/triggered_buffer.h>
|
||||
#include "../common/hid-sensors/hid-sensor-trigger.h"
|
||||
|
||||
/*Format: HID-SENSOR-usage_id_in_hex*/
|
||||
/*Usage ID from spec for Gyro-3D: 0x200076*/
|
||||
#define DRIVER_NAME "HID-SENSOR-200076"
|
||||
|
||||
enum gyro_3d_channel {
|
||||
CHANNEL_SCAN_INDEX_X,
|
||||
CHANNEL_SCAN_INDEX_Y,
|
||||
|
@ -179,18 +175,10 @@ static int gyro_3d_write_raw(struct iio_dev *indio_dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int gyro_3d_write_raw_get_fmt(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
long mask)
|
||||
{
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
}
|
||||
|
||||
static const struct iio_info gyro_3d_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = &gyro_3d_read_raw,
|
||||
.write_raw = &gyro_3d_write_raw,
|
||||
.write_raw_get_fmt = &gyro_3d_write_raw_get_fmt,
|
||||
};
|
||||
|
||||
/* Function to push data to buffer */
|
||||
|
@ -286,11 +274,9 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
|
|||
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
|
||||
struct iio_chan_spec *channels;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(struct gyro_3d_state));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*gyro_state));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
|
||||
gyro_state = iio_priv(indio_dev);
|
||||
|
@ -302,15 +288,14 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
|
|||
&gyro_state->common_attributes);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to setup common attributes\n");
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
}
|
||||
|
||||
channels = kmemdup(gyro_3d_channels, sizeof(gyro_3d_channels),
|
||||
GFP_KERNEL);
|
||||
if (!channels) {
|
||||
ret = -ENOMEM;
|
||||
dev_err(&pdev->dev, "failed to duplicate channels\n");
|
||||
goto error_free_dev;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = gyro_3d_parse_report(pdev, hsdev, channels,
|
||||
|
@ -367,9 +352,6 @@ error_unreg_buffer_funcs:
|
|||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
error_free_dev_mem:
|
||||
kfree(indio_dev->channels);
|
||||
error_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -384,14 +366,23 @@ static int hid_gyro_3d_remove(struct platform_device *pdev)
|
|||
hid_sensor_remove_trigger(indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
kfree(indio_dev->channels);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_device_id hid_gyro_3d_ids[] = {
|
||||
{
|
||||
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
|
||||
.name = "HID-SENSOR-200076",
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, hid_gyro_3d_ids);
|
||||
|
||||
static struct platform_driver hid_gyro_3d_platform_driver = {
|
||||
.id_table = hid_gyro_3d_ids,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.name = KBUILD_MODNAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = hid_gyro_3d_probe,
|
||||
|
|
|
@ -309,11 +309,9 @@ static int itg3200_probe(struct i2c_client *client,
|
|||
|
||||
dev_dbg(&client->dev, "probe I2C dev with IRQ %i", client->irq);
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
|
@ -330,7 +328,7 @@ static int itg3200_probe(struct i2c_client *client,
|
|||
|
||||
ret = itg3200_buffer_configure(indio_dev);
|
||||
if (ret)
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
|
||||
if (client->irq) {
|
||||
ret = itg3200_probe_trigger(indio_dev);
|
||||
|
@ -353,9 +351,6 @@ error_remove_trigger:
|
|||
itg3200_remove_trigger(indio_dev);
|
||||
error_unconfigure_buffer:
|
||||
itg3200_buffer_unconfigure(indio_dev);
|
||||
error_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -370,8 +365,6 @@ static int itg3200_remove(struct i2c_client *client)
|
|||
|
||||
itg3200_buffer_unconfigure(indio_dev);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,16 @@
|
|||
#define L3G4IS_GYRO_DEV_NAME "l3g4is_ui"
|
||||
#define LSM330_GYRO_DEV_NAME "lsm330_gyro"
|
||||
|
||||
int st_gyro_common_probe(struct iio_dev *indio_dev);
|
||||
/**
|
||||
* struct st_sensors_platform_data - gyro platform data
|
||||
* @drdy_int_pin: DRDY on gyros is available only on INT2 pin.
|
||||
*/
|
||||
static const struct st_sensors_platform_data gyro_pdata = {
|
||||
.drdy_int_pin = 2,
|
||||
};
|
||||
|
||||
int st_gyro_common_probe(struct iio_dev *indio_dev,
|
||||
struct st_sensors_platform_data *pdata);
|
||||
void st_gyro_common_remove(struct iio_dev *indio_dev);
|
||||
|
||||
#ifdef CONFIG_IIO_BUFFER
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
#define ST_GYRO_1_BDU_ADDR 0x23
|
||||
#define ST_GYRO_1_BDU_MASK 0x80
|
||||
#define ST_GYRO_1_DRDY_IRQ_ADDR 0x22
|
||||
#define ST_GYRO_1_DRDY_IRQ_MASK 0x08
|
||||
#define ST_GYRO_1_DRDY_IRQ_INT2_MASK 0x08
|
||||
#define ST_GYRO_1_MULTIREAD_BIT true
|
||||
|
||||
/* CUSTOM VALUES FOR SENSOR 2 */
|
||||
|
@ -84,7 +84,7 @@
|
|||
#define ST_GYRO_2_BDU_ADDR 0x23
|
||||
#define ST_GYRO_2_BDU_MASK 0x80
|
||||
#define ST_GYRO_2_DRDY_IRQ_ADDR 0x22
|
||||
#define ST_GYRO_2_DRDY_IRQ_MASK 0x08
|
||||
#define ST_GYRO_2_DRDY_IRQ_INT2_MASK 0x08
|
||||
#define ST_GYRO_2_MULTIREAD_BIT true
|
||||
|
||||
static const struct iio_chan_spec st_gyro_16bit_channels[] = {
|
||||
|
@ -158,7 +158,7 @@ static const struct st_sensors st_gyro_sensors[] = {
|
|||
},
|
||||
.drdy_irq = {
|
||||
.addr = ST_GYRO_1_DRDY_IRQ_ADDR,
|
||||
.mask = ST_GYRO_1_DRDY_IRQ_MASK,
|
||||
.mask_int2 = ST_GYRO_1_DRDY_IRQ_INT2_MASK,
|
||||
},
|
||||
.multi_read_bit = ST_GYRO_1_MULTIREAD_BIT,
|
||||
.bootime = 2,
|
||||
|
@ -221,7 +221,7 @@ static const struct st_sensors st_gyro_sensors[] = {
|
|||
},
|
||||
.drdy_irq = {
|
||||
.addr = ST_GYRO_2_DRDY_IRQ_ADDR,
|
||||
.mask = ST_GYRO_2_DRDY_IRQ_MASK,
|
||||
.mask_int2 = ST_GYRO_2_DRDY_IRQ_INT2_MASK,
|
||||
},
|
||||
.multi_read_bit = ST_GYRO_2_MULTIREAD_BIT,
|
||||
.bootime = 2,
|
||||
|
@ -302,7 +302,8 @@ static const struct iio_trigger_ops st_gyro_trigger_ops = {
|
|||
#define ST_GYRO_TRIGGER_OPS NULL
|
||||
#endif
|
||||
|
||||
int st_gyro_common_probe(struct iio_dev *indio_dev)
|
||||
int st_gyro_common_probe(struct iio_dev *indio_dev,
|
||||
struct st_sensors_platform_data *pdata)
|
||||
{
|
||||
int err;
|
||||
struct st_sensor_data *gdata = iio_priv(indio_dev);
|
||||
|
@ -324,7 +325,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
|
|||
&gdata->sensor->fs.fs_avl[0];
|
||||
gdata->odr = gdata->sensor->odr.odr_avl[0].hz;
|
||||
|
||||
err = st_sensors_init_sensor(indio_dev);
|
||||
err = st_sensors_init_sensor(indio_dev, pdata);
|
||||
if (err < 0)
|
||||
goto st_gyro_common_probe_error;
|
||||
|
||||
|
@ -365,7 +366,6 @@ void st_gyro_common_remove(struct iio_dev *indio_dev)
|
|||
st_sensors_deallocate_trigger(indio_dev);
|
||||
st_gyro_deallocate_ring(indio_dev);
|
||||
}
|
||||
iio_device_free(indio_dev);
|
||||
}
|
||||
EXPORT_SYMBOL(st_gyro_common_remove);
|
||||
|
||||
|
|
|
@ -25,27 +25,21 @@ static int st_gyro_i2c_probe(struct i2c_client *client,
|
|||
struct st_sensor_data *gdata;
|
||||
int err;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*gdata));
|
||||
if (indio_dev == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto iio_device_alloc_error;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*gdata));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
gdata = iio_priv(indio_dev);
|
||||
gdata->dev = &client->dev;
|
||||
|
||||
st_sensors_i2c_configure(indio_dev, client, gdata);
|
||||
|
||||
err = st_gyro_common_probe(indio_dev);
|
||||
err = st_gyro_common_probe(indio_dev,
|
||||
(struct st_sensors_platform_data *)&gyro_pdata);
|
||||
if (err < 0)
|
||||
goto st_gyro_common_probe_error;
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
|
||||
st_gyro_common_probe_error:
|
||||
iio_device_free(indio_dev);
|
||||
iio_device_alloc_error:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int st_gyro_i2c_remove(struct i2c_client *client)
|
||||
|
|
|
@ -24,27 +24,21 @@ static int st_gyro_spi_probe(struct spi_device *spi)
|
|||
struct st_sensor_data *gdata;
|
||||
int err;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*gdata));
|
||||
if (indio_dev == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto iio_device_alloc_error;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*gdata));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
gdata = iio_priv(indio_dev);
|
||||
gdata->dev = &spi->dev;
|
||||
|
||||
st_sensors_spi_configure(indio_dev, spi, gdata);
|
||||
|
||||
err = st_gyro_common_probe(indio_dev);
|
||||
err = st_gyro_common_probe(indio_dev,
|
||||
(struct st_sensors_platform_data *)&gyro_pdata);
|
||||
if (err < 0)
|
||||
goto st_gyro_common_probe_error;
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
|
||||
st_gyro_common_probe_error:
|
||||
iio_device_free(indio_dev);
|
||||
iio_device_alloc_error:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int st_gyro_spi_remove(struct spi_device *spi)
|
||||
|
|
|
@ -30,7 +30,7 @@ void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev);
|
|||
static int iio_device_register_trigger_consumer(struct iio_dev *indio_dev)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* iio_device_unregister_trigger_consumer() - reverse the registration process
|
||||
|
@ -38,9 +38,6 @@ static int iio_device_register_trigger_consumer(struct iio_dev *indio_dev)
|
|||
**/
|
||||
static void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev)
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* CONFIG_TRIGGER_CONSUMER */
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# IIO imu drivers configuration
|
||||
#
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
|
||||
menu "Inertial measurement units"
|
||||
|
||||
config ADIS16400
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
# Makefile for Inertial Measurement Units
|
||||
#
|
||||
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
adis16400-y := adis16400_core.o
|
||||
adis16400-$(CONFIG_IIO_BUFFER) += adis16400_buffer.o
|
||||
obj-$(CONFIG_ADIS16400) += adis16400.o
|
||||
|
|
|
@ -871,7 +871,7 @@ static int adis16400_probe(struct spi_device *spi)
|
|||
struct iio_dev *indio_dev;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -893,12 +893,12 @@ static int adis16400_probe(struct spi_device *spi)
|
|||
|
||||
ret = adis_init(&st->adis, indio_dev, spi, &adis16400_data);
|
||||
if (ret)
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
|
||||
ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev,
|
||||
adis16400_trigger_handler);
|
||||
if (ret)
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
|
||||
/* Get the device into a sane initial state */
|
||||
ret = adis16400_initial_setup(indio_dev);
|
||||
|
@ -913,8 +913,6 @@ static int adis16400_probe(struct spi_device *spi)
|
|||
|
||||
error_cleanup_buffer:
|
||||
adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
|
||||
error_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -928,8 +926,6 @@ static int adis16400_remove(struct spi_device *spi)
|
|||
|
||||
adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -839,7 +839,7 @@ static int adis16480_probe(struct spi_device *spi)
|
|||
struct adis16480 *st;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -857,11 +857,11 @@ static int adis16480_probe(struct spi_device *spi)
|
|||
|
||||
ret = adis_init(&st->adis, indio_dev, spi, &adis16480_data);
|
||||
if (ret)
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
|
||||
ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL);
|
||||
if (ret)
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
|
||||
ret = adis16480_initial_setup(indio_dev);
|
||||
if (ret)
|
||||
|
@ -879,8 +879,6 @@ error_stop_device:
|
|||
adis16480_stop_device(indio_dev);
|
||||
error_cleanup_buffer:
|
||||
adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
|
||||
error_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -894,8 +892,6 @@ static int adis16480_remove(struct spi_device *spi)
|
|||
|
||||
adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include "inv_mpu_iio.h"
|
||||
|
||||
/*
|
||||
|
@ -663,16 +664,13 @@ static int inv_mpu_probe(struct i2c_client *client,
|
|||
int result;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_READ_I2C_BLOCK |
|
||||
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
|
||||
result = -ENOSYS;
|
||||
goto out_no_free;
|
||||
}
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
result = -ENOMEM;
|
||||
goto out_no_free;
|
||||
}
|
||||
I2C_FUNC_SMBUS_I2C_BLOCK))
|
||||
return -ENOSYS;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
st->client = client;
|
||||
st->plat_data = *(struct inv_mpu6050_platform_data
|
||||
|
@ -680,13 +678,13 @@ static int inv_mpu_probe(struct i2c_client *client,
|
|||
/* power is turned on inside check chip type*/
|
||||
result = inv_check_and_setup_chip(st, id);
|
||||
if (result)
|
||||
goto out_free;
|
||||
return result;
|
||||
|
||||
result = inv_mpu6050_init_config(indio_dev);
|
||||
if (result) {
|
||||
dev_err(&client->dev,
|
||||
"Could not initialize device.\n");
|
||||
goto out_free;
|
||||
return result;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
|
@ -705,7 +703,7 @@ static int inv_mpu_probe(struct i2c_client *client,
|
|||
if (result) {
|
||||
dev_err(&st->client->dev, "configure buffer fail %d\n",
|
||||
result);
|
||||
goto out_free;
|
||||
return result;
|
||||
}
|
||||
result = inv_mpu6050_probe_trigger(indio_dev);
|
||||
if (result) {
|
||||
|
@ -727,10 +725,6 @@ out_remove_trigger:
|
|||
inv_mpu6050_remove_trigger(st);
|
||||
out_unreg_ring:
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
out_free:
|
||||
iio_device_free(indio_dev);
|
||||
out_no_free:
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -742,7 +736,6 @@ static int inv_mpu_remove(struct i2c_client *client)
|
|||
iio_device_unregister(indio_dev);
|
||||
inv_mpu6050_remove_trigger(st);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -383,14 +383,14 @@ static ssize_t iio_read_channel_info(struct device *dev,
|
|||
scale_db = true;
|
||||
case IIO_VAL_INT_PLUS_MICRO:
|
||||
if (val2 < 0)
|
||||
return sprintf(buf, "-%d.%06u%s\n", val, -val2,
|
||||
return sprintf(buf, "-%ld.%06u%s\n", abs(val), -val2,
|
||||
scale_db ? " dB" : "");
|
||||
else
|
||||
return sprintf(buf, "%d.%06u%s\n", val, val2,
|
||||
scale_db ? " dB" : "");
|
||||
case IIO_VAL_INT_PLUS_NANO:
|
||||
if (val2 < 0)
|
||||
return sprintf(buf, "-%d.%09u\n", val, -val2);
|
||||
return sprintf(buf, "-%ld.%09u\n", abs(val), -val2);
|
||||
else
|
||||
return sprintf(buf, "%d.%09u\n", val, val2);
|
||||
case IIO_VAL_FRACTIONAL:
|
||||
|
@ -912,6 +912,53 @@ void iio_device_free(struct iio_dev *dev)
|
|||
}
|
||||
EXPORT_SYMBOL(iio_device_free);
|
||||
|
||||
static void devm_iio_device_release(struct device *dev, void *res)
|
||||
{
|
||||
iio_device_free(*(struct iio_dev **)res);
|
||||
}
|
||||
|
||||
static int devm_iio_device_match(struct device *dev, void *res, void *data)
|
||||
{
|
||||
struct iio_dev **r = res;
|
||||
if (!r || !*r) {
|
||||
WARN_ON(!r || !*r);
|
||||
return 0;
|
||||
}
|
||||
return *r == data;
|
||||
}
|
||||
|
||||
struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv)
|
||||
{
|
||||
struct iio_dev **ptr, *iio_dev;
|
||||
|
||||
ptr = devres_alloc(devm_iio_device_release, sizeof(*ptr),
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
|
||||
/* use raw alloc_dr for kmalloc caller tracing */
|
||||
iio_dev = iio_device_alloc(sizeof_priv);
|
||||
if (iio_dev) {
|
||||
*ptr = iio_dev;
|
||||
devres_add(dev, ptr);
|
||||
} else {
|
||||
devres_free(ptr);
|
||||
}
|
||||
|
||||
return iio_dev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_device_alloc);
|
||||
|
||||
void devm_iio_device_free(struct device *dev, struct iio_dev *iio_dev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = devres_release(dev, devm_iio_device_release,
|
||||
devm_iio_device_match, iio_dev);
|
||||
WARN_ON(rc);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_device_free);
|
||||
|
||||
/**
|
||||
* iio_chrdev_open() - chrdev file open for buffer access and ioctls
|
||||
**/
|
||||
|
|
|
@ -424,9 +424,8 @@ static void iio_trig_subirqunmask(struct irq_data *d)
|
|||
trig->subirqs[d->irq - trig->subirq_base].enabled = true;
|
||||
}
|
||||
|
||||
struct iio_trigger *iio_trigger_alloc(const char *fmt, ...)
|
||||
static struct iio_trigger *viio_trigger_alloc(const char *fmt, va_list vargs)
|
||||
{
|
||||
va_list vargs;
|
||||
struct iio_trigger *trig;
|
||||
trig = kzalloc(sizeof *trig, GFP_KERNEL);
|
||||
if (trig) {
|
||||
|
@ -444,9 +443,8 @@ struct iio_trigger *iio_trigger_alloc(const char *fmt, ...)
|
|||
kfree(trig);
|
||||
return NULL;
|
||||
}
|
||||
va_start(vargs, fmt);
|
||||
|
||||
trig->name = kvasprintf(GFP_KERNEL, fmt, vargs);
|
||||
va_end(vargs);
|
||||
if (trig->name == NULL) {
|
||||
irq_free_descs(trig->subirq_base,
|
||||
CONFIG_IIO_CONSUMERS_PER_TRIGGER);
|
||||
|
@ -467,6 +465,19 @@ struct iio_trigger *iio_trigger_alloc(const char *fmt, ...)
|
|||
}
|
||||
get_device(&trig->dev);
|
||||
}
|
||||
|
||||
return trig;
|
||||
}
|
||||
|
||||
struct iio_trigger *iio_trigger_alloc(const char *fmt, ...)
|
||||
{
|
||||
struct iio_trigger *trig;
|
||||
va_list vargs;
|
||||
|
||||
va_start(vargs, fmt);
|
||||
trig = viio_trigger_alloc(fmt, vargs);
|
||||
va_end(vargs);
|
||||
|
||||
return trig;
|
||||
}
|
||||
EXPORT_SYMBOL(iio_trigger_alloc);
|
||||
|
@ -478,6 +489,59 @@ void iio_trigger_free(struct iio_trigger *trig)
|
|||
}
|
||||
EXPORT_SYMBOL(iio_trigger_free);
|
||||
|
||||
static void devm_iio_trigger_release(struct device *dev, void *res)
|
||||
{
|
||||
iio_trigger_free(*(struct iio_trigger **)res);
|
||||
}
|
||||
|
||||
static int devm_iio_trigger_match(struct device *dev, void *res, void *data)
|
||||
{
|
||||
struct iio_trigger **r = res;
|
||||
|
||||
if (!r || !*r) {
|
||||
WARN_ON(!r || !*r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return *r == data;
|
||||
}
|
||||
|
||||
struct iio_trigger *devm_iio_trigger_alloc(struct device *dev,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
struct iio_trigger **ptr, *trig;
|
||||
va_list vargs;
|
||||
|
||||
ptr = devres_alloc(devm_iio_trigger_release, sizeof(*ptr),
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
|
||||
/* use raw alloc_dr for kmalloc caller tracing */
|
||||
va_start(vargs, fmt);
|
||||
trig = viio_trigger_alloc(fmt, vargs);
|
||||
va_end(vargs);
|
||||
if (trig) {
|
||||
*ptr = trig;
|
||||
devres_add(dev, ptr);
|
||||
} else {
|
||||
devres_free(ptr);
|
||||
}
|
||||
|
||||
return trig;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_trigger_alloc);
|
||||
|
||||
void devm_iio_trigger_free(struct device *dev, struct iio_trigger *iio_trig)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = devres_release(dev, devm_iio_trigger_release,
|
||||
devm_iio_trigger_match, iio_trig);
|
||||
WARN_ON(rc);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_trigger_free);
|
||||
|
||||
void iio_device_register_trigger_consumer(struct iio_dev *indio_dev)
|
||||
{
|
||||
indio_dev->groups[indio_dev->groupcounter++] =
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# Light sensors
|
||||
#
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
|
||||
menu "Light sensors"
|
||||
|
||||
config ADJD_S311
|
||||
|
@ -15,6 +17,27 @@ config ADJD_S311
|
|||
This driver can also be built as a module. If so, the module
|
||||
will be called adjd_s311.
|
||||
|
||||
config APDS9300
|
||||
tristate "APDS9300 ambient light sensor"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you want to build a driver for the Avago APDS9300
|
||||
ambient light sensor.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called apds9300.
|
||||
|
||||
config HID_SENSOR_ALS
|
||||
depends on HID_SENSOR_HUB
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
select HID_SENSOR_IIO_COMMON
|
||||
select HID_SENSOR_IIO_TRIGGER
|
||||
tristate "HID ALS"
|
||||
help
|
||||
Say yes here to build support for the HID SENSOR
|
||||
Ambient light sensor.
|
||||
|
||||
config SENSORS_LM3533
|
||||
tristate "LM3533 ambient light sensor"
|
||||
depends on MFD_LM3533
|
||||
|
@ -52,15 +75,4 @@ config VCNL4000
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called vcnl4000.
|
||||
|
||||
config HID_SENSOR_ALS
|
||||
depends on HID_SENSOR_HUB
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
select HID_SENSOR_IIO_COMMON
|
||||
select HID_SENSOR_IIO_TRIGGER
|
||||
tristate "HID ALS"
|
||||
help
|
||||
Say yes here to build support for the HID SENSOR
|
||||
Ambient light sensor.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
# Makefile for IIO Light sensors
|
||||
#
|
||||
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
obj-$(CONFIG_ADJD_S311) += adjd_s311.o
|
||||
obj-$(CONFIG_APDS9300) += apds9300.o
|
||||
obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o
|
||||
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
|
||||
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
|
||||
obj-$(CONFIG_VCNL4000) += vcnl4000.o
|
||||
obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o
|
||||
|
|
|
@ -37,22 +37,14 @@
|
|||
#define ADJD_S311_CAP_GREEN 0x07
|
||||
#define ADJD_S311_CAP_BLUE 0x08
|
||||
#define ADJD_S311_CAP_CLEAR 0x09
|
||||
#define ADJD_S311_INT_RED_LO 0x0a
|
||||
#define ADJD_S311_INT_RED_HI 0x0b
|
||||
#define ADJD_S311_INT_GREEN_LO 0x0c
|
||||
#define ADJD_S311_INT_GREEN_HI 0x0d
|
||||
#define ADJD_S311_INT_BLUE_LO 0x0e
|
||||
#define ADJD_S311_INT_BLUE_HI 0x0f
|
||||
#define ADJD_S311_INT_CLEAR_LO 0x10
|
||||
#define ADJD_S311_INT_CLEAR_HI 0x11
|
||||
#define ADJD_S311_DATA_RED_LO 0x40
|
||||
#define ADJD_S311_DATA_RED_HI 0x41
|
||||
#define ADJD_S311_DATA_GREEN_LO 0x42
|
||||
#define ADJD_S311_DATA_GREEN_HI 0x43
|
||||
#define ADJD_S311_DATA_BLUE_LO 0x44
|
||||
#define ADJD_S311_DATA_BLUE_HI 0x45
|
||||
#define ADJD_S311_DATA_CLEAR_LO 0x46
|
||||
#define ADJD_S311_DATA_CLEAR_HI 0x47
|
||||
#define ADJD_S311_INT_RED 0x0a
|
||||
#define ADJD_S311_INT_GREEN 0x0c
|
||||
#define ADJD_S311_INT_BLUE 0x0e
|
||||
#define ADJD_S311_INT_CLEAR 0x10
|
||||
#define ADJD_S311_DATA_RED 0x40
|
||||
#define ADJD_S311_DATA_GREEN 0x42
|
||||
#define ADJD_S311_DATA_BLUE 0x44
|
||||
#define ADJD_S311_DATA_CLEAR 0x46
|
||||
#define ADJD_S311_OFFSET_RED 0x48
|
||||
#define ADJD_S311_OFFSET_GREEN 0x49
|
||||
#define ADJD_S311_OFFSET_BLUE 0x4a
|
||||
|
@ -73,8 +65,8 @@ enum adjd_s311_channel_idx {
|
|||
IDX_RED, IDX_GREEN, IDX_BLUE, IDX_CLEAR
|
||||
};
|
||||
|
||||
#define ADJD_S311_DATA_REG(chan) (ADJD_S311_DATA_RED_LO + (chan) * 2)
|
||||
#define ADJD_S311_INT_REG(chan) (ADJD_S311_INT_RED_LO + (chan) * 2)
|
||||
#define ADJD_S311_DATA_REG(chan) (ADJD_S311_DATA_RED + (chan) * 2)
|
||||
#define ADJD_S311_INT_REG(chan) (ADJD_S311_INT_RED + (chan) * 2)
|
||||
#define ADJD_S311_CAP_REG(chan) (ADJD_S311_CAP_RED + (chan))
|
||||
|
||||
static int adjd_s311_req_data(struct iio_dev *indio_dev)
|
||||
|
@ -294,11 +286,10 @@ static int adjd_s311_probe(struct i2c_client *client,
|
|||
struct iio_dev *indio_dev;
|
||||
int err;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*data));
|
||||
if (indio_dev == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
data = iio_priv(indio_dev);
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
data->client = client;
|
||||
|
@ -313,7 +304,7 @@ static int adjd_s311_probe(struct i2c_client *client,
|
|||
err = iio_triggered_buffer_setup(indio_dev, NULL,
|
||||
adjd_s311_trigger_handler, NULL);
|
||||
if (err < 0)
|
||||
goto exit_free_device;
|
||||
return err;
|
||||
|
||||
err = iio_device_register(indio_dev);
|
||||
if (err)
|
||||
|
@ -325,9 +316,6 @@ static int adjd_s311_probe(struct i2c_client *client,
|
|||
|
||||
exit_unreg_buffer:
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
exit_free_device:
|
||||
iio_device_free(indio_dev);
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -339,7 +327,6 @@ static int adjd_s311_remove(struct i2c_client *client)
|
|||
iio_device_unregister(indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
kfree(data->buffer);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,512 @@
|
|||
/*
|
||||
* apds9300.c - IIO driver for Avago APDS9300 ambient light sensor
|
||||
*
|
||||
* Copyright 2013 Oleksandr Kravchenko <o.v.kravchenko@globallogic.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/events.h>
|
||||
|
||||
#define APDS9300_DRV_NAME "apds9300"
|
||||
#define APDS9300_IRQ_NAME "apds9300_event"
|
||||
|
||||
/* Command register bits */
|
||||
#define APDS9300_CMD BIT(7) /* Select command register. Must write as 1 */
|
||||
#define APDS9300_WORD BIT(5) /* I2C write/read: if 1 word, if 0 byte */
|
||||
#define APDS9300_CLEAR BIT(6) /* Interrupt clear. Clears pending interrupt */
|
||||
|
||||
/* Register set */
|
||||
#define APDS9300_CONTROL 0x00 /* Control of basic functions */
|
||||
#define APDS9300_THRESHLOWLOW 0x02 /* Low byte of low interrupt threshold */
|
||||
#define APDS9300_THRESHHIGHLOW 0x04 /* Low byte of high interrupt threshold */
|
||||
#define APDS9300_INTERRUPT 0x06 /* Interrupt control */
|
||||
#define APDS9300_DATA0LOW 0x0c /* Low byte of ADC channel 0 */
|
||||
#define APDS9300_DATA1LOW 0x0e /* Low byte of ADC channel 1 */
|
||||
|
||||
/* Power on/off value for APDS9300_CONTROL register */
|
||||
#define APDS9300_POWER_ON 0x03
|
||||
#define APDS9300_POWER_OFF 0x00
|
||||
|
||||
/* Interrupts */
|
||||
#define APDS9300_INTR_ENABLE 0x10
|
||||
/* Interrupt Persist Function: Any value outside of threshold range */
|
||||
#define APDS9300_THRESH_INTR 0x01
|
||||
|
||||
#define APDS9300_THRESH_MAX 0xffff /* Max threshold value */
|
||||
|
||||
struct apds9300_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex mutex;
|
||||
int power_state;
|
||||
int thresh_low;
|
||||
int thresh_hi;
|
||||
int intr_en;
|
||||
};
|
||||
|
||||
/* Lux calculation */
|
||||
|
||||
/* Calculated values 1000 * (CH1/CH0)^1.4 for CH1/CH0 from 0 to 0.52 */
|
||||
static const u16 apds9300_lux_ratio[] = {
|
||||
0, 2, 4, 7, 11, 15, 19, 24, 29, 34, 40, 45, 51, 57, 64, 70, 77, 84, 91,
|
||||
98, 105, 112, 120, 128, 136, 144, 152, 160, 168, 177, 185, 194, 203,
|
||||
212, 221, 230, 239, 249, 258, 268, 277, 287, 297, 307, 317, 327, 337,
|
||||
347, 358, 368, 379, 390, 400,
|
||||
};
|
||||
|
||||
static unsigned long apds9300_calculate_lux(u16 ch0, u16 ch1)
|
||||
{
|
||||
unsigned long lux, tmp;
|
||||
|
||||
/* avoid division by zero */
|
||||
if (ch0 == 0)
|
||||
return 0;
|
||||
|
||||
tmp = DIV_ROUND_UP(ch1 * 100, ch0);
|
||||
if (tmp <= 52) {
|
||||
lux = 3150 * ch0 - (unsigned long)DIV_ROUND_UP_ULL(ch0
|
||||
* apds9300_lux_ratio[tmp] * 5930ull, 1000);
|
||||
} else if (tmp <= 65) {
|
||||
lux = 2290 * ch0 - 2910 * ch1;
|
||||
} else if (tmp <= 80) {
|
||||
lux = 1570 * ch0 - 1800 * ch1;
|
||||
} else if (tmp <= 130) {
|
||||
lux = 338 * ch0 - 260 * ch1;
|
||||
} else {
|
||||
lux = 0;
|
||||
}
|
||||
|
||||
return lux / 100000;
|
||||
}
|
||||
|
||||
static int apds9300_get_adc_val(struct apds9300_data *data, int adc_number)
|
||||
{
|
||||
int ret;
|
||||
u8 flags = APDS9300_CMD | APDS9300_WORD;
|
||||
|
||||
if (!data->power_state)
|
||||
return -EBUSY;
|
||||
|
||||
/* Select ADC0 or ADC1 data register */
|
||||
flags |= adc_number ? APDS9300_DATA1LOW : APDS9300_DATA0LOW;
|
||||
|
||||
ret = i2c_smbus_read_word_data(data->client, flags);
|
||||
if (ret < 0)
|
||||
dev_err(&data->client->dev,
|
||||
"failed to read ADC%d value\n", adc_number);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int apds9300_set_thresh_low(struct apds9300_data *data, int value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!data->power_state)
|
||||
return -EBUSY;
|
||||
|
||||
if (value > APDS9300_THRESH_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
ret = i2c_smbus_write_word_data(data->client, APDS9300_THRESHLOWLOW
|
||||
| APDS9300_CMD | APDS9300_WORD, value);
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev, "failed to set thresh_low\n");
|
||||
return ret;
|
||||
}
|
||||
data->thresh_low = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apds9300_set_thresh_hi(struct apds9300_data *data, int value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!data->power_state)
|
||||
return -EBUSY;
|
||||
|
||||
if (value > APDS9300_THRESH_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
ret = i2c_smbus_write_word_data(data->client, APDS9300_THRESHHIGHLOW
|
||||
| APDS9300_CMD | APDS9300_WORD, value);
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev, "failed to set thresh_hi\n");
|
||||
return ret;
|
||||
}
|
||||
data->thresh_hi = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apds9300_set_intr_state(struct apds9300_data *data, int state)
|
||||
{
|
||||
int ret;
|
||||
u8 cmd;
|
||||
|
||||
if (!data->power_state)
|
||||
return -EBUSY;
|
||||
|
||||
cmd = state ? APDS9300_INTR_ENABLE | APDS9300_THRESH_INTR : 0x00;
|
||||
ret = i2c_smbus_write_byte_data(data->client,
|
||||
APDS9300_INTERRUPT | APDS9300_CMD, cmd);
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev,
|
||||
"failed to set interrupt state %d\n", state);
|
||||
return ret;
|
||||
}
|
||||
data->intr_en = state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apds9300_set_power_state(struct apds9300_data *data, int state)
|
||||
{
|
||||
int ret;
|
||||
u8 cmd;
|
||||
|
||||
cmd = state ? APDS9300_POWER_ON : APDS9300_POWER_OFF;
|
||||
ret = i2c_smbus_write_byte_data(data->client,
|
||||
APDS9300_CONTROL | APDS9300_CMD, cmd);
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev,
|
||||
"failed to set power state %d\n", state);
|
||||
return ret;
|
||||
}
|
||||
data->power_state = state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void apds9300_clear_intr(struct apds9300_data *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_smbus_write_byte(data->client, APDS9300_CLEAR | APDS9300_CMD);
|
||||
if (ret < 0)
|
||||
dev_err(&data->client->dev, "failed to clear interrupt\n");
|
||||
}
|
||||
|
||||
static int apds9300_chip_init(struct apds9300_data *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Need to set power off to ensure that the chip is off */
|
||||
ret = apds9300_set_power_state(data, 0);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
/*
|
||||
* Probe the chip. To do so we try to power up the device and then to
|
||||
* read back the 0x03 code
|
||||
*/
|
||||
ret = apds9300_set_power_state(data, 1);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
ret = i2c_smbus_read_byte_data(data->client,
|
||||
APDS9300_CONTROL | APDS9300_CMD);
|
||||
if (ret != APDS9300_POWER_ON) {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* Disable interrupt to ensure thai it is doesn't enable
|
||||
* i.e. after device soft reset
|
||||
*/
|
||||
ret = apds9300_set_intr_state(data, 0);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
dev_err(&data->client->dev, "failed to init the chip\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int apds9300_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan, int *val, int *val2,
|
||||
long mask)
|
||||
{
|
||||
int ch0, ch1, ret = -EINVAL;
|
||||
struct apds9300_data *data = iio_priv(indio_dev);
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
switch (chan->type) {
|
||||
case IIO_LIGHT:
|
||||
ch0 = apds9300_get_adc_val(data, 0);
|
||||
if (ch0 < 0) {
|
||||
ret = ch0;
|
||||
break;
|
||||
}
|
||||
ch1 = apds9300_get_adc_val(data, 1);
|
||||
if (ch1 < 0) {
|
||||
ret = ch1;
|
||||
break;
|
||||
}
|
||||
*val = apds9300_calculate_lux(ch0, ch1);
|
||||
ret = IIO_VAL_INT;
|
||||
break;
|
||||
case IIO_INTENSITY:
|
||||
ret = apds9300_get_adc_val(data, chan->channel);
|
||||
if (ret < 0)
|
||||
break;
|
||||
*val = ret;
|
||||
ret = IIO_VAL_INT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int apds9300_read_thresh(struct iio_dev *indio_dev, u64 event_code,
|
||||
int *val)
|
||||
{
|
||||
struct apds9300_data *data = iio_priv(indio_dev);
|
||||
|
||||
switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
|
||||
case IIO_EV_DIR_RISING:
|
||||
*val = data->thresh_hi;
|
||||
break;
|
||||
case IIO_EV_DIR_FALLING:
|
||||
*val = data->thresh_low;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apds9300_write_thresh(struct iio_dev *indio_dev, u64 event_code,
|
||||
int val)
|
||||
{
|
||||
struct apds9300_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING)
|
||||
ret = apds9300_set_thresh_hi(data, val);
|
||||
else
|
||||
ret = apds9300_set_thresh_low(data, val);
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int apds9300_read_interrupt_config(struct iio_dev *indio_dev,
|
||||
u64 event_code)
|
||||
{
|
||||
struct apds9300_data *data = iio_priv(indio_dev);
|
||||
|
||||
return data->intr_en;
|
||||
}
|
||||
|
||||
static int apds9300_write_interrupt_config(struct iio_dev *indio_dev,
|
||||
u64 event_code, int state)
|
||||
{
|
||||
struct apds9300_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
ret = apds9300_set_intr_state(data, state);
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct iio_info apds9300_info_no_irq = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = apds9300_read_raw,
|
||||
};
|
||||
|
||||
static const struct iio_info apds9300_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = apds9300_read_raw,
|
||||
.read_event_value = apds9300_read_thresh,
|
||||
.write_event_value = apds9300_write_thresh,
|
||||
.read_event_config = apds9300_read_interrupt_config,
|
||||
.write_event_config = apds9300_write_interrupt_config,
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec apds9300_channels[] = {
|
||||
{
|
||||
.type = IIO_LIGHT,
|
||||
.channel = 0,
|
||||
.indexed = true,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
|
||||
}, {
|
||||
.type = IIO_INTENSITY,
|
||||
.channel = 0,
|
||||
.channel2 = IIO_MOD_LIGHT_BOTH,
|
||||
.indexed = true,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
.event_mask = (IIO_EV_BIT(IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_RISING) |
|
||||
IIO_EV_BIT(IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_FALLING)),
|
||||
}, {
|
||||
.type = IIO_INTENSITY,
|
||||
.channel = 1,
|
||||
.channel2 = IIO_MOD_LIGHT_IR,
|
||||
.indexed = true,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
},
|
||||
};
|
||||
|
||||
static irqreturn_t apds9300_interrupt_handler(int irq, void *private)
|
||||
{
|
||||
struct iio_dev *dev_info = private;
|
||||
struct apds9300_data *data = iio_priv(dev_info);
|
||||
|
||||
iio_push_event(dev_info,
|
||||
IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, 0,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_EITHER),
|
||||
iio_get_time_ns());
|
||||
|
||||
apds9300_clear_intr(data);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int apds9300_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct apds9300_data *data;
|
||||
struct iio_dev *indio_dev;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
data = iio_priv(indio_dev);
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
data->client = client;
|
||||
|
||||
ret = apds9300_chip_init(data);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
mutex_init(&data->mutex);
|
||||
|
||||
indio_dev->dev.parent = &client->dev;
|
||||
indio_dev->channels = apds9300_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(apds9300_channels);
|
||||
indio_dev->name = APDS9300_DRV_NAME;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
if (client->irq)
|
||||
indio_dev->info = &apds9300_info;
|
||||
else
|
||||
indio_dev->info = &apds9300_info_no_irq;
|
||||
|
||||
if (client->irq) {
|
||||
ret = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL, apds9300_interrupt_handler,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
APDS9300_IRQ_NAME, indio_dev);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "irq request error %d\n", -ret);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
/* Ensure that power off in case of error */
|
||||
apds9300_set_power_state(data, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int apds9300_remove(struct i2c_client *client)
|
||||
{
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
||||
struct apds9300_data *data = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
|
||||
/* Ensure that power off and interrupts are disabled */
|
||||
apds9300_set_intr_state(data, 0);
|
||||
apds9300_set_power_state(data, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int apds9300_suspend(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
|
||||
struct apds9300_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
ret = apds9300_set_power_state(data, 0);
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int apds9300_resume(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
|
||||
struct apds9300_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
ret = apds9300_set_power_state(data, 1);
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(apds9300_pm_ops, apds9300_suspend, apds9300_resume);
|
||||
#define APDS9300_PM_OPS (&apds9300_pm_ops)
|
||||
#else
|
||||
#define APDS9300_PM_OPS NULL
|
||||
#endif
|
||||
|
||||
static struct i2c_device_id apds9300_id[] = {
|
||||
{ APDS9300_DRV_NAME, 0 },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, apds9300_id);
|
||||
|
||||
static struct i2c_driver apds9300_driver = {
|
||||
.driver = {
|
||||
.name = APDS9300_DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = APDS9300_PM_OPS,
|
||||
},
|
||||
.probe = apds9300_probe,
|
||||
.remove = apds9300_remove,
|
||||
.id_table = apds9300_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(apds9300_driver);
|
||||
|
||||
MODULE_AUTHOR("Kravchenko Oleksandr <o.v.kravchenko@globallogic.com>");
|
||||
MODULE_AUTHOR("GlobalLogic inc.");
|
||||
MODULE_DESCRIPTION("APDS9300 ambient light photo sensor driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -30,10 +30,6 @@
|
|||
#include <linux/iio/triggered_buffer.h>
|
||||
#include "../common/hid-sensors/hid-sensor-trigger.h"
|
||||
|
||||
/*Format: HID-SENSOR-usage_id_in_hex*/
|
||||
/*Usage ID from spec for Ambiant-Light: 0x200041*/
|
||||
#define DRIVER_NAME "HID-SENSOR-200041"
|
||||
|
||||
#define CHANNEL_SCAN_INDEX_ILLUM 0
|
||||
|
||||
struct als_state {
|
||||
|
@ -158,18 +154,10 @@ static int als_write_raw(struct iio_dev *indio_dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int als_write_raw_get_fmt(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
long mask)
|
||||
{
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
}
|
||||
|
||||
static const struct iio_info als_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = &als_read_raw,
|
||||
.write_raw = &als_write_raw,
|
||||
.write_raw_get_fmt = &als_write_raw_get_fmt,
|
||||
};
|
||||
|
||||
/* Function to push data to buffer */
|
||||
|
@ -253,11 +241,9 @@ static int hid_als_probe(struct platform_device *pdev)
|
|||
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
|
||||
struct iio_chan_spec *channels;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(struct als_state));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct als_state));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
|
||||
als_state = iio_priv(indio_dev);
|
||||
|
@ -268,14 +254,13 @@ static int hid_als_probe(struct platform_device *pdev)
|
|||
&als_state->common_attributes);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to setup common attributes\n");
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
}
|
||||
|
||||
channels = kmemdup(als_channels, sizeof(als_channels), GFP_KERNEL);
|
||||
if (!channels) {
|
||||
ret = -ENOMEM;
|
||||
dev_err(&pdev->dev, "failed to duplicate channels\n");
|
||||
goto error_free_dev;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = als_parse_report(pdev, hsdev, channels,
|
||||
|
@ -333,9 +318,6 @@ error_unreg_buffer_funcs:
|
|||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
error_free_dev_mem:
|
||||
kfree(indio_dev->channels);
|
||||
error_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -350,14 +332,23 @@ static int hid_als_remove(struct platform_device *pdev)
|
|||
hid_sensor_remove_trigger(indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
kfree(indio_dev->channels);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_device_id hid_als_ids[] = {
|
||||
{
|
||||
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
|
||||
.name = "HID-SENSOR-200041",
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, hid_als_ids);
|
||||
|
||||
static struct platform_driver hid_als_platform_driver = {
|
||||
.id_table = hid_als_ids,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.name = KBUILD_MODNAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = hid_als_probe,
|
||||
|
|
|
@ -847,7 +847,7 @@ static int lm3533_als_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*als));
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*als));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -870,7 +870,7 @@ static int lm3533_als_probe(struct platform_device *pdev)
|
|||
if (als->irq) {
|
||||
ret = lm3533_als_setup_irq(als, indio_dev);
|
||||
if (ret)
|
||||
goto err_free_dev;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = lm3533_als_setup(als, pdata);
|
||||
|
@ -894,8 +894,6 @@ err_disable:
|
|||
err_free_irq:
|
||||
if (als->irq)
|
||||
free_irq(als->irq, indio_dev);
|
||||
err_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -910,7 +908,6 @@ static int lm3533_als_remove(struct platform_device *pdev)
|
|||
lm3533_als_disable(als);
|
||||
if (als->irq)
|
||||
free_irq(als->irq, indio_dev);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -702,7 +702,7 @@ static int tsl2563_probe(struct i2c_client *client,
|
|||
int err = 0;
|
||||
u8 id = 0;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*chip));
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -714,13 +714,13 @@ static int tsl2563_probe(struct i2c_client *client,
|
|||
err = tsl2563_detect(chip);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "detect error %d\n", -err);
|
||||
goto fail1;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = tsl2563_read_id(chip, &id);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "read id error %d\n", -err);
|
||||
goto fail1;
|
||||
return err;
|
||||
}
|
||||
|
||||
mutex_init(&chip->lock);
|
||||
|
@ -751,7 +751,7 @@ static int tsl2563_probe(struct i2c_client *client,
|
|||
indio_dev->info = &tsl2563_info_no_irq;
|
||||
|
||||
if (client->irq) {
|
||||
err = request_threaded_irq(client->irq,
|
||||
err = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL,
|
||||
&tsl2563_event_handler,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
|
@ -759,14 +759,14 @@ static int tsl2563_probe(struct i2c_client *client,
|
|||
indio_dev);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "irq request error %d\n", -err);
|
||||
goto fail1;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = tsl2563_configure(chip);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "configure error %d\n", -err);
|
||||
goto fail2;
|
||||
return err;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&chip->poweroff_work, tsl2563_poweroff_work);
|
||||
|
@ -777,19 +777,14 @@ static int tsl2563_probe(struct i2c_client *client,
|
|||
err = iio_device_register(indio_dev);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "iio registration error %d\n", -err);
|
||||
goto fail3;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail3:
|
||||
fail:
|
||||
cancel_delayed_work(&chip->poweroff_work);
|
||||
flush_scheduled_work();
|
||||
fail2:
|
||||
if (client->irq)
|
||||
free_irq(client->irq, indio_dev);
|
||||
fail1:
|
||||
iio_device_free(indio_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -807,10 +802,6 @@ static int tsl2563_remove(struct i2c_client *client)
|
|||
chip->intr);
|
||||
flush_scheduled_work();
|
||||
tsl2563_set_power(chip, 0);
|
||||
if (client->irq)
|
||||
free_irq(client->irq, indio_dev);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ static int vcnl4000_probe(struct i2c_client *client,
|
|||
struct iio_dev *indio_dev;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*data));
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -167,7 +167,7 @@ static int vcnl4000_probe(struct i2c_client *client,
|
|||
|
||||
ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV);
|
||||
if (ret < 0)
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
|
||||
dev_info(&client->dev, "VCNL4000 Ambient light/proximity sensor, Prod %02x, Rev: %02x\n",
|
||||
ret >> 4, ret & 0xf);
|
||||
|
@ -181,22 +181,14 @@ static int vcnl4000_probe(struct i2c_client *client,
|
|||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret < 0)
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
|
||||
error_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vcnl4000_remove(struct i2c_client *client)
|
||||
{
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
iio_device_unregister(i2c_get_clientdata(client));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# Magnetometer sensors
|
||||
#
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
|
||||
menu "Magnetometer sensors"
|
||||
|
||||
config AK8975
|
||||
|
@ -36,8 +38,8 @@ config IIO_ST_MAGN_3AXIS
|
|||
Say yes here to build support for STMicroelectronics magnetometers:
|
||||
LSM303DLHC, LSM303DLM, LIS3MDL.
|
||||
|
||||
This driver can also be built as a module. If so, will be created
|
||||
these modules:
|
||||
This driver can also be built as a module. If so, these modules
|
||||
will be created:
|
||||
- st_magn (core functions for the driver [it is mandatory]);
|
||||
- st_magn_i2c (necessary for the I2C devices [optional*]);
|
||||
- st_magn_spi (necessary for the SPI devices [optional*]);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
# Makefile for industrial I/O Magnetometer sensor drivers
|
||||
#
|
||||
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
obj-$(CONFIG_AK8975) += ak8975.o
|
||||
obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
|
||||
|
||||
|
|
|
@ -30,10 +30,6 @@
|
|||
#include <linux/iio/triggered_buffer.h>
|
||||
#include "../common/hid-sensors/hid-sensor-trigger.h"
|
||||
|
||||
/*Format: HID-SENSOR-usage_id_in_hex*/
|
||||
/*Usage ID from spec for Magnetometer-3D: 0x200083*/
|
||||
#define DRIVER_NAME "HID-SENSOR-200083"
|
||||
|
||||
enum magn_3d_channel {
|
||||
CHANNEL_SCAN_INDEX_X,
|
||||
CHANNEL_SCAN_INDEX_Y,
|
||||
|
@ -180,18 +176,10 @@ static int magn_3d_write_raw(struct iio_dev *indio_dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int magn_3d_write_raw_get_fmt(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
long mask)
|
||||
{
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
}
|
||||
|
||||
static const struct iio_info magn_3d_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = &magn_3d_read_raw,
|
||||
.write_raw = &magn_3d_write_raw,
|
||||
.write_raw_get_fmt = &magn_3d_write_raw_get_fmt,
|
||||
};
|
||||
|
||||
/* Function to push data to buffer */
|
||||
|
@ -287,11 +275,11 @@ static int hid_magn_3d_probe(struct platform_device *pdev)
|
|||
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
|
||||
struct iio_chan_spec *channels;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(struct magn_3d_state));
|
||||
if (indio_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev,
|
||||
sizeof(struct magn_3d_state));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
|
||||
magn_state = iio_priv(indio_dev);
|
||||
|
@ -303,15 +291,14 @@ static int hid_magn_3d_probe(struct platform_device *pdev)
|
|||
&magn_state->common_attributes);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to setup common attributes\n");
|
||||
goto error_free_dev;
|
||||
return ret;
|
||||
}
|
||||
|
||||
channels = kmemdup(magn_3d_channels, sizeof(magn_3d_channels),
|
||||
GFP_KERNEL);
|
||||
if (!channels) {
|
||||
ret = -ENOMEM;
|
||||
dev_err(&pdev->dev, "failed to duplicate channels\n");
|
||||
goto error_free_dev;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = magn_3d_parse_report(pdev, hsdev, channels,
|
||||
|
@ -368,9 +355,6 @@ error_unreg_buffer_funcs:
|
|||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
error_free_dev_mem:
|
||||
kfree(indio_dev->channels);
|
||||
error_free_dev:
|
||||
iio_device_free(indio_dev);
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -385,14 +369,23 @@ static int hid_magn_3d_remove(struct platform_device *pdev)
|
|||
hid_sensor_remove_trigger(indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
kfree(indio_dev->channels);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_device_id hid_magn_3d_ids[] = {
|
||||
{
|
||||
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
|
||||
.name = "HID-SENSOR-200083",
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, hid_magn_3d_ids);
|
||||
|
||||
static struct platform_driver hid_magn_3d_platform_driver = {
|
||||
.id_table = hid_magn_3d_ids,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.name = KBUILD_MODNAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = hid_magn_3d_probe,
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
#define LSM303DLM_MAGN_DEV_NAME "lsm303dlm_magn"
|
||||
#define LIS3MDL_MAGN_DEV_NAME "lis3mdl"
|
||||
|
||||
int st_magn_common_probe(struct iio_dev *indio_dev);
|
||||
int st_magn_common_probe(struct iio_dev *indio_dev,
|
||||
struct st_sensors_platform_data *pdata);
|
||||
void st_magn_common_remove(struct iio_dev *indio_dev);
|
||||
|
||||
#ifdef CONFIG_IIO_BUFFER
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue