Watch
1
Fork
You've already forked kernel_a52xq
0
mirror of https://github.com/a52xq-dev/kernel.git synced 2026-10-18 21:58:11 +07:00

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

Device Support
 * ad5761
   - new driver
 * at91_sama5d2 ADC.
   - new driver and MAINTAINERS entry.
   - minor cleanups followed.
 * atlas pH-SM
   - new driver (this has possibly the prettiest data sheet I've ever seen)
 * mcp3422
   - mcp3425 ADC added.
 * mcp4725
   - mcp4726 DAC added.
 * mma8452
   - mma8451q accelerometer added.
 * mpl115
   - mpl115a1 added (a lot bigger than it seems as this is an SPI part whereas
     previous parts were i2c).
 * si7005
   - Hoperf th02 (seems to be a repackaged part)
 * si7020
   - Hoperf th06 (seems to be a repackaged part)
 
 New features
 * Core
   - IIO_PH type. Does what it says on the tin.
 * max30100
   - LED current configuration support.
 * mcp320x
   - more differential measurement combinations.
 * mma8452
   - free fall deteciton
 - opt3001
   - enable operation without a IRQ line.
   - device tree docs.  Somehow the original docs have disappeared down
     a rabbit hole, so here is a new set.
 * st-sensors
   - Support active-low interrupts.
 
 Cleanups and minor / not so minor reworks
 * Documentation
   - drop some defunct ABI from the docs in staging.
 * presure / Kconfig
   - white space cleanup.
 * ad7150
   - BIT macro usage
   - Alignment fixes
 * ad7192
   - false indent fixed.
 * ak8975
   - constify the ak_def structures
 * axp288
   - drop a redundant double const.
 * dht11
   - substantial reliability improvements by being more tolerant
     of missing start bits.
   - simplify the decoding algorithm
 * mma8452
   - whitespace cleanup
 * mpl115
   - don't bother setting i2c_client_data as nothing uses it.
 * mpu6050
   - drop unused function parameter.
 * opt3001
   - extract integration time as constants.
   - trivial refactoring.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJWr8HEAAoJEFSFNJnE9BaIIWMP/A6hJdAi3QOipB75QYBHL3R2
 7fe7Bcd83i2to/Ohk9XirRwyP7kCqt1ZP7cnaIAevNxmwQ9fqIFgrxCK8BfF+lMk
 60PXfEdinPk1rWguqEMwaYq1xVAOTgWYl8F4GVG3nGIvTHovAYaZW0UcTUl5Gz+l
 WErEZQ5xgnf7e/29ds74eD3YaOti8E1mzhBLXFJH7lllsSMJttbp9Xb5J0QJrv4a
 Ly8Ru5DBRGZYKi0VplFIjncKLZgX/VUUSPNL+NXtPnGD2Qp2zx0bJ3eIqNmeEYZl
 isAGIc6l4XPXQLczyRaPbcQLobMxOHMP2uuXxY/OAbe2DX9/6ILcB2QigARAFHf2
 7vVcx3JlxXUtwS/bPpZSd5hHrvjWLR7+gyuZTA4b/scV4+GvknMl8e6IIh4Ux3/T
 d24V37bOIENrXCoyf81veap0xca6xQNSzCVuo8+1+QYqn6DxvoJw3p38Cmxb8eB8
 7M+nQJP9SwLtbSUak8g1KVrtWBNsMrMGwoiuZq5SkK1PQTSXnSaJPTL0OoPoefNi
 uIY5qD5FrUp9jlNbBP2M2E3CcG5CJcMElxyBgd7F5lEVxSWPOuyOcpJHIoCCCgIf
 o6vwOYXXfD4ytv/E6jg+Bbv3ZYCylFhcoZOqPgTC/sOnSI9RwhJ6XdAg6VU8sv07
 piH1AVWb91HKRN2dt2ZB
 =fgTH
 -----END PGP SIGNATURE-----

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

Jonathan writes:

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

Device Support
* ad5761
  - new driver
* at91_sama5d2 ADC.
  - new driver and MAINTAINERS entry.
  - minor cleanups followed.
* atlas pH-SM
  - new driver (this has possibly the prettiest data sheet I've ever seen)
* mcp3422
  - mcp3425 ADC added.
* mcp4725
  - mcp4726 DAC added.
* mma8452
  - mma8451q accelerometer added.
* mpl115
  - mpl115a1 added (a lot bigger than it seems as this is an SPI part whereas
    previous parts were i2c).
* si7005
  - Hoperf th02 (seems to be a repackaged part)
* si7020
  - Hoperf th06 (seems to be a repackaged part)

New features
* Core
  - IIO_PH type. Does what it says on the tin.
* max30100
  - LED current configuration support.
* mcp320x
  - more differential measurement combinations.
* mma8452
  - free fall deteciton
- opt3001
  - enable operation without a IRQ line.
  - device tree docs.  Somehow the original docs have disappeared down
    a rabbit hole, so here is a new set.
* st-sensors
  - Support active-low interrupts.

Cleanups and minor / not so minor reworks
* Documentation
  - drop some defunct ABI from the docs in staging.
* presure / Kconfig
  - white space cleanup.
* ad7150
  - BIT macro usage
  - Alignment fixes
* ad7192
  - false indent fixed.
* ak8975
  - constify the ak_def structures
* axp288
  - drop a redundant double const.
* dht11
  - substantial reliability improvements by being more tolerant
    of missing start bits.
  - simplify the decoding algorithm
* mma8452
  - whitespace cleanup
* mpl115
  - don't bother setting i2c_client_data as nothing uses it.
* mpu6050
  - drop unused function parameter.
* opt3001
  - extract integration time as constants.
  - trivial refactoring.
This commit is contained in:
Greg Kroah-Hartman 2016-02-01 13:10:03 -08:00
commit fec2f3335c
53 changed files with 2531 additions and 265 deletions

View file

@ -3054,6 +3054,7 @@ D: PLX USB338x driver
D: PCA9634 driver
D: Option GTM671WFS
D: Fintek F81216A
D: AD5761 iio driver
D: Various kernel hacks
S: Qtechnology A/S
S: Valby Langgade 142

View file

@ -497,7 +497,9 @@ 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,
125kohm_to_gnd: connected to ground via an 125kOhm resistor,
500kohm_to_gnd: connected to ground via a 500kOhm resistor,
640kohm_to_gnd: connected to ground via a 640kOhm 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
@ -1491,3 +1493,10 @@ Description:
This ABI is especially applicable for humidity sensors
to heatup the device and get rid of any condensation
in some humidity environment
What: /sys/bus/iio/devices/iio:deviceX/in_ph_raw
KernelVersion: 4.5
Contact: linux-iio@vger.kernel.org
Description:
Raw (unscaled no offset etc.) pH reading of a substance as a negative
base-10 logarithm of hydrodium ions in a litre of water.

View file

@ -1,8 +1,10 @@
Freescale MMA8452Q, MMA8453Q, MMA8652FC or MMA8653FC triaxial accelerometer
Freescale MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC or MMA8653FC
triaxial accelerometer
Required properties:
- compatible: should contain one of
* "fsl,mma8451"
* "fsl,mma8452"
* "fsl,mma8453"
* "fsl,mma8652"

View file

@ -0,0 +1,28 @@
* AT91 SAMA5D2 Analog to Digital Converter (ADC)
Required properties:
- compatible: Should be "atmel,sama5d2-adc".
- reg: Should contain ADC registers location and length.
- interrupts: Should contain the IRQ line for the ADC.
- clocks: phandle to device clock.
- clock-names: Must be "adc_clk".
- vref-supply: Supply used as reference for conversions.
- vddana-supply: Supply for the adc device.
- atmel,min-sample-rate-hz: Minimum sampling rate, it depends on SoC.
- atmel,max-sample-rate-hz: Maximum sampling rate, it depends on SoC.
- atmel,startup-time-ms: Startup time expressed in ms, it depends on SoC.
Example:
adc: adc@fc030000 {
compatible = "atmel,sama5d2-adc";
reg = <0xfc030000 0x100>;
interrupts = <40 IRQ_TYPE_LEVEL_HIGH 7>;
clocks = <&adc_clk>;
clock-names = "adc_clk";
atmel,min-sample-rate-hz = <200000>;
atmel,max-sample-rate-hz = <20000000>;
atmel,startup-time-ms = <4>;
vddana-supply = <&vdd_3v3_lp_reg>;
vref-supply = <&vdd_3v3_lp_reg>;
}

View file

@ -6,6 +6,7 @@ Required properties:
"microchip,mcp3422" or
"microchip,mcp3423" or
"microchip,mcp3424" or
"microchip,mcp3425" or
"microchip,mcp3426" or
"microchip,mcp3427" or
"microchip,mcp3428"

View file

@ -0,0 +1,22 @@
* Atlas Scientific pH-SM OEM sensor
http://www.atlas-scientific.com/_files/_datasheets/_oem/pH_oem_datasheet.pdf
Required properties:
- compatible: must be "atlas,ph-sm"
- reg: the I2C address of the sensor
- interrupt-parent: should be the phandle for the interrupt controller
- interrupts: the sole interrupt generated by the device
Refer to interrupt-controller/interrupts.txt for generic interrupt client
node bindings.
Example:
atlas@65 {
compatible = "atlas,ph-sm";
reg = <0x65>;
interrupt-parent = <&gpio1>;
interrupts = <16 2>;
};

View file

@ -11,11 +11,19 @@ Required properties:
Refer to interrupt-controller/interrupts.txt for generic
interrupt client node bindings.
Optional properties:
- maxim,led-current-microamp: configuration for LED current in microamperes
while the engine is running. First indexed value is the configuration for
the RED LED, and second value is for the IR LED.
Refer to the datasheet for the allowed current values.
Example:
max30100@057 {
compatible = "maxim,max30100";
reg = <57>;
maxim,led-current-microamp = <24000 50000>;
interrupt-parent = <&gpio1>;
interrupts = <16 2>;
};

View file

@ -0,0 +1,26 @@
* Texas Instruments OPT3001 Ambient Light Sensor
The driver supports interrupt-driven and interrupt-less operation, depending
on whether an interrupt property has been populated into the DT. Note that
the optional generation of IIO events on rising/falling light threshold changes
requires the use of interrupts. Without interrupts, only the simple reading
of the current light value is supported through the IIO API.
http://www.ti.com/product/opt3001
Required properties:
- compatible: should be "ti,opt3001"
- 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 (configure for falling edge)
Example:
opt3001@44 {
compatible = "ti,opt3001";
reg = <0x44>;
interrupt-parent = <&gpio1>;
interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
};

View file

@ -28,6 +28,7 @@ arm ARM Ltd.
armadeus ARMadeus Systems SARL
artesyn Artesyn Embedded Technologies Inc.
asahi-kasei Asahi Kasei Corp.
atlas Atlas Scientific LLC
atmel Atmel Corporation
auo AU Optronics Corporation
avago Avago Technologies

View file

@ -1945,6 +1945,12 @@ M: Nicolas Ferre <nicolas.ferre@atmel.com>
S: Supported
F: drivers/tty/serial/atmel_serial.c
ATMEL SAMA5D2 ADC DRIVER
M: Ludovic Desroches <ludovic.desroches@atmel.com>
L: linux-iio@vger.kernel.org
S: Supported
F: drivers/iio/adc/at91-sama5d2_adc.c
ATMEL Audio ALSA driver
M: Nicolas Ferre <nicolas.ferre@atmel.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)

View file

@ -143,7 +143,7 @@ config MMA8452
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for the following Freescale 3-axis
accelerometers: MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC.
accelerometers: MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC.
To compile this driver as a module, choose M here: the module
will be called mma8452.

View file

@ -1,6 +1,7 @@
/*
* mma8452.c - Support for following Freescale 3-axis accelerometers:
*
* MMA8451Q (14 bit)
* MMA8452Q (12 bit)
* MMA8453Q (10 bit)
* MMA8652FC (12 bit)
@ -15,7 +16,7 @@
*
* 7-bit I2C slave address 0x1c/0x1d (pin selectable)
*
* TODO: orientation / freefall events, autosleep
* TODO: orientation events, autosleep
*/
#include <linux/module.h>
@ -85,8 +86,9 @@
#define MMA8452_INT_FF_MT BIT(2)
#define MMA8452_INT_TRANS BIT(5)
#define MMA8452_DEVICE_ID 0x2a
#define MMA8453_DEVICE_ID 0x3a
#define MMA8451_DEVICE_ID 0x1a
#define MMA8452_DEVICE_ID 0x2a
#define MMA8453_DEVICE_ID 0x3a
#define MMA8652_DEVICE_ID 0x4a
#define MMA8653_DEVICE_ID 0x5a
@ -416,6 +418,51 @@ fail:
return ret;
}
/* returns >0 if in freefall mode, 0 if not or <0 if an error occured */
static int mma8452_freefall_mode_enabled(struct mma8452_data *data)
{
int val;
const struct mma_chip_info *chip = data->chip_info;
val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg);
if (val < 0)
return val;
return !(val & MMA8452_FF_MT_CFG_OAE);
}
static int mma8452_set_freefall_mode(struct mma8452_data *data, bool state)
{
int val;
const struct mma_chip_info *chip = data->chip_info;
if ((state && mma8452_freefall_mode_enabled(data)) ||
(!state && !(mma8452_freefall_mode_enabled(data))))
return 0;
val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg);
if (val < 0)
return val;
if (state) {
val |= BIT(idx_x + chip->ev_cfg_chan_shift);
val |= BIT(idx_y + chip->ev_cfg_chan_shift);
val |= BIT(idx_z + chip->ev_cfg_chan_shift);
val &= ~MMA8452_FF_MT_CFG_OAE;
} else {
val &= ~BIT(idx_x + chip->ev_cfg_chan_shift);
val &= ~BIT(idx_y + chip->ev_cfg_chan_shift);
val &= ~BIT(idx_z + chip->ev_cfg_chan_shift);
val |= MMA8452_FF_MT_CFG_OAE;
}
val = mma8452_change_config(data, chip->ev_cfg, val);
if (val)
return val;
return 0;
}
static int mma8452_set_hp_filter_frequency(struct mma8452_data *data,
int val, int val2)
{
@ -609,12 +656,22 @@ static int mma8452_read_event_config(struct iio_dev *indio_dev,
const struct mma_chip_info *chip = data->chip_info;
int ret;
ret = i2c_smbus_read_byte_data(data->client,
data->chip_info->ev_cfg);
if (ret < 0)
return ret;
switch (dir) {
case IIO_EV_DIR_FALLING:
return mma8452_freefall_mode_enabled(data);
case IIO_EV_DIR_RISING:
if (mma8452_freefall_mode_enabled(data))
return 0;
return !!(ret & BIT(chan->scan_index + chip->ev_cfg_chan_shift));
ret = i2c_smbus_read_byte_data(data->client,
data->chip_info->ev_cfg);
if (ret < 0)
return ret;
return !!(ret & BIT(chan->scan_index + chip->ev_cfg_chan_shift));
default:
return -EINVAL;
}
}
static int mma8452_write_event_config(struct iio_dev *indio_dev,
@ -627,19 +684,35 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev,
const struct mma_chip_info *chip = data->chip_info;
int val;
val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg);
if (val < 0)
return val;
switch (dir) {
case IIO_EV_DIR_FALLING:
return mma8452_set_freefall_mode(data, state);
case IIO_EV_DIR_RISING:
val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg);
if (val < 0)
return val;
if (state)
val |= BIT(chan->scan_index + chip->ev_cfg_chan_shift);
else
val &= ~BIT(chan->scan_index + chip->ev_cfg_chan_shift);
if (state) {
if (mma8452_freefall_mode_enabled(data)) {
val &= ~BIT(idx_x + chip->ev_cfg_chan_shift);
val &= ~BIT(idx_y + chip->ev_cfg_chan_shift);
val &= ~BIT(idx_z + chip->ev_cfg_chan_shift);
val |= MMA8452_FF_MT_CFG_OAE;
}
val |= BIT(chan->scan_index + chip->ev_cfg_chan_shift);
} else {
if (mma8452_freefall_mode_enabled(data))
return 0;
val |= chip->ev_cfg_ele;
val |= MMA8452_FF_MT_CFG_OAE;
val &= ~BIT(chan->scan_index + chip->ev_cfg_chan_shift);
}
return mma8452_change_config(data, chip->ev_cfg, val);
val |= chip->ev_cfg_ele;
return mma8452_change_config(data, chip->ev_cfg, val);
default:
return -EINVAL;
}
}
static void mma8452_transient_interrupt(struct iio_dev *indio_dev)
@ -652,6 +725,16 @@ static void mma8452_transient_interrupt(struct iio_dev *indio_dev)
if (src < 0)
return;
if (mma8452_freefall_mode_enabled(data)) {
iio_push_event(indio_dev,
IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,
IIO_MOD_X_AND_Y_AND_Z,
IIO_EV_TYPE_MAG,
IIO_EV_DIR_FALLING),
ts);
return;
}
if (src & data->chip_info->ev_src_xe)
iio_push_event(indio_dev,
IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X,
@ -745,6 +828,27 @@ static int mma8452_reg_access_dbg(struct iio_dev *indio_dev,
return 0;
}
static const struct iio_event_spec mma8452_freefall_event[] = {
{
.type = IIO_EV_TYPE_MAG,
.dir = IIO_EV_DIR_FALLING,
.mask_separate = BIT(IIO_EV_INFO_ENABLE),
.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_PERIOD) |
BIT(IIO_EV_INFO_HIGH_PASS_FILTER_3DB)
},
};
static const struct iio_event_spec mma8652_freefall_event[] = {
{
.type = IIO_EV_TYPE_MAG,
.dir = IIO_EV_DIR_FALLING,
.mask_separate = BIT(IIO_EV_INFO_ENABLE),
.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_PERIOD)
},
};
static const struct iio_event_spec mma8452_transient_event[] = {
{
.type = IIO_EV_TYPE_MAG,
@ -781,6 +885,24 @@ static struct attribute_group mma8452_event_attribute_group = {
.attrs = mma8452_event_attributes,
};
#define MMA8452_FREEFALL_CHANNEL(modifier) { \
.type = IIO_ACCEL, \
.modified = 1, \
.channel2 = modifier, \
.scan_index = -1, \
.event_spec = mma8452_freefall_event, \
.num_event_specs = ARRAY_SIZE(mma8452_freefall_event), \
}
#define MMA8652_FREEFALL_CHANNEL(modifier) { \
.type = IIO_ACCEL, \
.modified = 1, \
.channel2 = modifier, \
.scan_index = -1, \
.event_spec = mma8652_freefall_event, \
.num_event_specs = ARRAY_SIZE(mma8652_freefall_event), \
}
#define MMA8452_CHANNEL(axis, idx, bits) { \
.type = IIO_ACCEL, \
.modified = 1, \
@ -822,11 +944,20 @@ static struct attribute_group mma8452_event_attribute_group = {
.num_event_specs = ARRAY_SIZE(mma8452_motion_event), \
}
static const struct iio_chan_spec mma8451_channels[] = {
MMA8452_CHANNEL(X, idx_x, 14),
MMA8452_CHANNEL(Y, idx_y, 14),
MMA8452_CHANNEL(Z, idx_z, 14),
IIO_CHAN_SOFT_TIMESTAMP(idx_ts),
MMA8452_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z),
};
static const struct iio_chan_spec mma8452_channels[] = {
MMA8452_CHANNEL(X, idx_x, 12),
MMA8452_CHANNEL(Y, idx_y, 12),
MMA8452_CHANNEL(Z, idx_z, 12),
IIO_CHAN_SOFT_TIMESTAMP(idx_ts),
MMA8452_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z),
};
static const struct iio_chan_spec mma8453_channels[] = {
@ -834,6 +965,7 @@ static const struct iio_chan_spec mma8453_channels[] = {
MMA8452_CHANNEL(Y, idx_y, 10),
MMA8452_CHANNEL(Z, idx_z, 10),
IIO_CHAN_SOFT_TIMESTAMP(idx_ts),
MMA8452_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z),
};
static const struct iio_chan_spec mma8652_channels[] = {
@ -841,6 +973,7 @@ static const struct iio_chan_spec mma8652_channels[] = {
MMA8652_CHANNEL(Y, idx_y, 12),
MMA8652_CHANNEL(Z, idx_z, 12),
IIO_CHAN_SOFT_TIMESTAMP(idx_ts),
MMA8652_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z),
};
static const struct iio_chan_spec mma8653_channels[] = {
@ -848,9 +981,11 @@ static const struct iio_chan_spec mma8653_channels[] = {
MMA8652_CHANNEL(Y, idx_y, 10),
MMA8652_CHANNEL(Z, idx_z, 10),
IIO_CHAN_SOFT_TIMESTAMP(idx_ts),
MMA8652_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z),
};
enum {
mma8451,
mma8452,
mma8453,
mma8652,
@ -858,17 +993,34 @@ enum {
};
static const struct mma_chip_info mma_chip_info_table[] = {
[mma8451] = {
.chip_id = MMA8451_DEVICE_ID,
.channels = mma8451_channels,
.num_channels = ARRAY_SIZE(mma8451_channels),
/*
* Hardware has fullscale of -2G, -4G, -8G corresponding to
* raw value -8192 for 14 bit, -2048 for 12 bit or -512 for 10
* bit.
* The userspace interface uses m/s^2 and we declare micro units
* So scale factor for 12 bit here is given by:
* g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
*/
.mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} },
.ev_cfg = MMA8452_TRANSIENT_CFG,
.ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
.ev_cfg_chan_shift = 1,
.ev_src = MMA8452_TRANSIENT_SRC,
.ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
.ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
.ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
.ev_ths = MMA8452_TRANSIENT_THS,
.ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
.ev_count = MMA8452_TRANSIENT_COUNT,
},
[mma8452] = {
.chip_id = MMA8452_DEVICE_ID,
.channels = mma8452_channels,
.num_channels = ARRAY_SIZE(mma8452_channels),
/*
* Hardware has fullscale of -2G, -4G, -8G corresponding to
* raw value -2048 for 12 bit or -512 for 10 bit.
* The userspace interface uses m/s^2 and we declare micro units
* So scale factor for 12 bit here is given by:
* g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
*/
.mma_scales = { {0, 9577}, {0, 19154}, {0, 38307} },
.ev_cfg = MMA8452_TRANSIENT_CFG,
.ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
@ -1049,6 +1201,7 @@ static int mma8452_reset(struct i2c_client *client)
}
static const struct of_device_id mma8452_dt_ids[] = {
{ .compatible = "fsl,mma8451", .data = &mma_chip_info_table[mma8451] },
{ .compatible = "fsl,mma8452", .data = &mma_chip_info_table[mma8452] },
{ .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] },
{ .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] },
@ -1085,6 +1238,7 @@ static int mma8452_probe(struct i2c_client *client,
return ret;
switch (ret) {
case MMA8451_DEVICE_ID:
case MMA8452_DEVICE_ID:
case MMA8453_DEVICE_ID:
case MMA8652_DEVICE_ID:
@ -1190,6 +1344,10 @@ static int mma8452_probe(struct i2c_client *client,
if (ret < 0)
goto buffer_cleanup;
ret = mma8452_set_freefall_mode(data, false);
if (ret)
return ret;
return 0;
buffer_cleanup:

View file

@ -67,6 +67,8 @@
#define ST_ACCEL_1_DRDY_IRQ_ADDR 0x22
#define ST_ACCEL_1_DRDY_IRQ_INT1_MASK 0x10
#define ST_ACCEL_1_DRDY_IRQ_INT2_MASK 0x08
#define ST_ACCEL_1_IHL_IRQ_ADDR 0x25
#define ST_ACCEL_1_IHL_IRQ_MASK 0x02
#define ST_ACCEL_1_MULTIREAD_BIT true
/* CUSTOM VALUES FOR SENSOR 2 */
@ -92,6 +94,8 @@
#define ST_ACCEL_2_DRDY_IRQ_ADDR 0x22
#define ST_ACCEL_2_DRDY_IRQ_INT1_MASK 0x02
#define ST_ACCEL_2_DRDY_IRQ_INT2_MASK 0x10
#define ST_ACCEL_2_IHL_IRQ_ADDR 0x22
#define ST_ACCEL_2_IHL_IRQ_MASK 0x80
#define ST_ACCEL_2_MULTIREAD_BIT true
/* CUSTOM VALUES FOR SENSOR 3 */
@ -125,6 +129,8 @@
#define ST_ACCEL_3_DRDY_IRQ_ADDR 0x23
#define ST_ACCEL_3_DRDY_IRQ_INT1_MASK 0x80
#define ST_ACCEL_3_DRDY_IRQ_INT2_MASK 0x00
#define ST_ACCEL_3_IHL_IRQ_ADDR 0x23
#define ST_ACCEL_3_IHL_IRQ_MASK 0x40
#define ST_ACCEL_3_IG1_EN_ADDR 0x23
#define ST_ACCEL_3_IG1_EN_MASK 0x08
#define ST_ACCEL_3_MULTIREAD_BIT false
@ -169,6 +175,8 @@
#define ST_ACCEL_5_DRDY_IRQ_ADDR 0x22
#define ST_ACCEL_5_DRDY_IRQ_INT1_MASK 0x04
#define ST_ACCEL_5_DRDY_IRQ_INT2_MASK 0x20
#define ST_ACCEL_5_IHL_IRQ_ADDR 0x22
#define ST_ACCEL_5_IHL_IRQ_MASK 0x80
#define ST_ACCEL_5_IG1_EN_ADDR 0x21
#define ST_ACCEL_5_IG1_EN_MASK 0x08
#define ST_ACCEL_5_MULTIREAD_BIT false
@ -292,6 +300,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.addr = ST_ACCEL_1_DRDY_IRQ_ADDR,
.mask_int1 = ST_ACCEL_1_DRDY_IRQ_INT1_MASK,
.mask_int2 = ST_ACCEL_1_DRDY_IRQ_INT2_MASK,
.addr_ihl = ST_ACCEL_1_IHL_IRQ_ADDR,
.mask_ihl = ST_ACCEL_1_IHL_IRQ_MASK,
},
.multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT,
.bootime = 2,
@ -355,6 +365,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.addr = ST_ACCEL_2_DRDY_IRQ_ADDR,
.mask_int1 = ST_ACCEL_2_DRDY_IRQ_INT1_MASK,
.mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK,
.addr_ihl = ST_ACCEL_2_IHL_IRQ_ADDR,
.mask_ihl = ST_ACCEL_2_IHL_IRQ_MASK,
},
.multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT,
.bootime = 2,
@ -430,6 +442,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.addr = ST_ACCEL_3_DRDY_IRQ_ADDR,
.mask_int1 = ST_ACCEL_3_DRDY_IRQ_INT1_MASK,
.mask_int2 = ST_ACCEL_3_DRDY_IRQ_INT2_MASK,
.addr_ihl = ST_ACCEL_3_IHL_IRQ_ADDR,
.mask_ihl = ST_ACCEL_3_IHL_IRQ_MASK,
.ig1 = {
.en_addr = ST_ACCEL_3_IG1_EN_ADDR,
.en_mask = ST_ACCEL_3_IG1_EN_MASK,
@ -537,6 +551,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.addr = ST_ACCEL_5_DRDY_IRQ_ADDR,
.mask_int1 = ST_ACCEL_5_DRDY_IRQ_INT1_MASK,
.mask_int2 = ST_ACCEL_5_DRDY_IRQ_INT2_MASK,
.addr_ihl = ST_ACCEL_5_IHL_IRQ_ADDR,
.mask_ihl = ST_ACCEL_5_IHL_IRQ_MASK,
},
.multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT,
.bootime = 2, /* guess */

View file

@ -131,6 +131,16 @@ config AT91_ADC
To compile this driver as a module, choose M here: the module will be
called at91_adc.
config AT91_SAMA5D2_ADC
tristate "Atmel AT91 SAMA5D2 ADC"
depends on ARCH_AT91 || COMPILE_TEST
help
Say yes here to build support for Atmel SAMA5D2 ADC which is
available on SAMA5D2 SoC family.
To compile this driver as a module, choose M here: the module will be
called at91-sama5d2_adc.
config AXP288_ADC
tristate "X-Powers AXP288 ADC driver"
depends on MFD_AXP20X
@ -265,11 +275,11 @@ config MCP320X
called mcp320x.
config MCP3422
tristate "Microchip Technology MCP3422/3/4/6/7/8 driver"
tristate "Microchip Technology MCP3421/2/3/4/5/6/7/8 driver"
depends on I2C
help
Say yes here to build support for Microchip Technology's
MCP3422, MCP3423, MCP3424, MCP3426, MCP3427 or MCP3428
Say yes here to build support for Microchip Technology's MCP3421
MCP3422, MCP3423, MCP3424, MCP3425, MCP3426, MCP3427 or MCP3428
analog to digital converters.
This driver can also be built as a module. If so, the module will be

View file

@ -14,6 +14,7 @@ obj-$(CONFIG_AD7793) += ad7793.o
obj-$(CONFIG_AD7887) += ad7887.o
obj-$(CONFIG_AD799X) += ad799x.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o
obj-$(CONFIG_AXP288_ADC) += axp288_adc.o
obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o
obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o

View file

@ -0,0 +1,508 @@
/*
* Atmel ADC driver for SAMA5D2 devices and compatible.
*
* Copyright (C) 2015 Atmel,
* 2015 Ludovic Desroches <ludovic.desroches@atmel.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/regulator/consumer.h>
/* Control Register */
#define AT91_SAMA5D2_CR 0x00
/* Software Reset */
#define AT91_SAMA5D2_CR_SWRST BIT(0)
/* Start Conversion */
#define AT91_SAMA5D2_CR_START BIT(1)
/* Touchscreen Calibration */
#define AT91_SAMA5D2_CR_TSCALIB BIT(2)
/* Comparison Restart */
#define AT91_SAMA5D2_CR_CMPRST BIT(4)
/* Mode Register */
#define AT91_SAMA5D2_MR 0x04
/* Trigger Selection */
#define AT91_SAMA5D2_MR_TRGSEL(v) ((v) << 1)
/* ADTRG */
#define AT91_SAMA5D2_MR_TRGSEL_TRIG0 0
/* TIOA0 */
#define AT91_SAMA5D2_MR_TRGSEL_TRIG1 1
/* TIOA1 */
#define AT91_SAMA5D2_MR_TRGSEL_TRIG2 2
/* TIOA2 */
#define AT91_SAMA5D2_MR_TRGSEL_TRIG3 3
/* PWM event line 0 */
#define AT91_SAMA5D2_MR_TRGSEL_TRIG4 4
/* PWM event line 1 */
#define AT91_SAMA5D2_MR_TRGSEL_TRIG5 5
/* TIOA3 */
#define AT91_SAMA5D2_MR_TRGSEL_TRIG6 6
/* RTCOUT0 */
#define AT91_SAMA5D2_MR_TRGSEL_TRIG7 7
/* Sleep Mode */
#define AT91_SAMA5D2_MR_SLEEP BIT(5)
/* Fast Wake Up */
#define AT91_SAMA5D2_MR_FWUP BIT(6)
/* Prescaler Rate Selection */
#define AT91_SAMA5D2_MR_PRESCAL(v) ((v) << AT91_SAMA5D2_MR_PRESCAL_OFFSET)
#define AT91_SAMA5D2_MR_PRESCAL_OFFSET 8
#define AT91_SAMA5D2_MR_PRESCAL_MAX 0xff
/* Startup Time */
#define AT91_SAMA5D2_MR_STARTUP(v) ((v) << 16)
/* Analog Change */
#define AT91_SAMA5D2_MR_ANACH BIT(23)
/* Tracking Time */
#define AT91_SAMA5D2_MR_TRACKTIM(v) ((v) << 24)
#define AT91_SAMA5D2_MR_TRACKTIM_MAX 0xff
/* Transfer Time */
#define AT91_SAMA5D2_MR_TRANSFER(v) ((v) << 28)
#define AT91_SAMA5D2_MR_TRANSFER_MAX 0x3
/* Use Sequence Enable */
#define AT91_SAMA5D2_MR_USEQ BIT(31)
/* Channel Sequence Register 1 */
#define AT91_SAMA5D2_SEQR1 0x08
/* Channel Sequence Register 2 */
#define AT91_SAMA5D2_SEQR2 0x0c
/* Channel Enable Register */
#define AT91_SAMA5D2_CHER 0x10
/* Channel Disable Register */
#define AT91_SAMA5D2_CHDR 0x14
/* Channel Status Register */
#define AT91_SAMA5D2_CHSR 0x18
/* Last Converted Data Register */
#define AT91_SAMA5D2_LCDR 0x20
/* Interrupt Enable Register */
#define AT91_SAMA5D2_IER 0x24
/* Interrupt Disable Register */
#define AT91_SAMA5D2_IDR 0x28
/* Interrupt Mask Register */
#define AT91_SAMA5D2_IMR 0x2c
/* Interrupt Status Register */
#define AT91_SAMA5D2_ISR 0x30
/* Last Channel Trigger Mode Register */
#define AT91_SAMA5D2_LCTMR 0x34
/* Last Channel Compare Window Register */
#define AT91_SAMA5D2_LCCWR 0x38
/* Overrun Status Register */
#define AT91_SAMA5D2_OVER 0x3c
/* Extended Mode Register */
#define AT91_SAMA5D2_EMR 0x40
/* Compare Window Register */
#define AT91_SAMA5D2_CWR 0x44
/* Channel Gain Register */
#define AT91_SAMA5D2_CGR 0x48
/* Channel Offset Register */
#define AT91_SAMA5D2_COR 0x4c
/* Channel Data Register 0 */
#define AT91_SAMA5D2_CDR0 0x50
/* Analog Control Register */
#define AT91_SAMA5D2_ACR 0x94
/* Touchscreen Mode Register */
#define AT91_SAMA5D2_TSMR 0xb0
/* Touchscreen X Position Register */
#define AT91_SAMA5D2_XPOSR 0xb4
/* Touchscreen Y Position Register */
#define AT91_SAMA5D2_YPOSR 0xb8
/* Touchscreen Pressure Register */
#define AT91_SAMA5D2_PRESSR 0xbc
/* Trigger Register */
#define AT91_SAMA5D2_TRGR 0xc0
/* Correction Select Register */
#define AT91_SAMA5D2_COSR 0xd0
/* Correction Value Register */
#define AT91_SAMA5D2_CVR 0xd4
/* Channel Error Correction Register */
#define AT91_SAMA5D2_CECR 0xd8
/* Write Protection Mode Register */
#define AT91_SAMA5D2_WPMR 0xe4
/* Write Protection Status Register */
#define AT91_SAMA5D2_WPSR 0xe8
/* Version Register */
#define AT91_SAMA5D2_VERSION 0xfc
#define AT91_AT91_SAMA5D2_CHAN(num, addr) \
{ \
.type = IIO_VOLTAGE, \
.channel = num, \
.address = addr, \
.scan_type = { \
.sign = 'u', \
.realbits = 12, \
}, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
.datasheet_name = "CH"#num, \
.indexed = 1, \
}
#define at91_adc_readl(st, reg) readl_relaxed(st->base + reg)
#define at91_adc_writel(st, reg, val) writel_relaxed(val, st->base + reg)
struct at91_adc_soc_info {
unsigned startup_time;
unsigned min_sample_rate;
unsigned max_sample_rate;
};
struct at91_adc_state {
void __iomem *base;
int irq;
struct clk *per_clk;
struct regulator *reg;
struct regulator *vref;
int vref_uv;
const struct iio_chan_spec *chan;
bool conversion_done;
u32 conversion_value;
struct at91_adc_soc_info soc_info;
wait_queue_head_t wq_data_available;
/*
* lock to prevent concurrent 'single conversion' requests through
* sysfs.
*/
struct mutex lock;
};
static const struct iio_chan_spec at91_adc_channels[] = {
AT91_AT91_SAMA5D2_CHAN(0, 0x50),
AT91_AT91_SAMA5D2_CHAN(1, 0x54),
AT91_AT91_SAMA5D2_CHAN(2, 0x58),
AT91_AT91_SAMA5D2_CHAN(3, 0x5c),
AT91_AT91_SAMA5D2_CHAN(4, 0x60),
AT91_AT91_SAMA5D2_CHAN(5, 0x64),
AT91_AT91_SAMA5D2_CHAN(6, 0x68),
AT91_AT91_SAMA5D2_CHAN(7, 0x6c),
AT91_AT91_SAMA5D2_CHAN(8, 0x70),
AT91_AT91_SAMA5D2_CHAN(9, 0x74),
AT91_AT91_SAMA5D2_CHAN(10, 0x78),
AT91_AT91_SAMA5D2_CHAN(11, 0x7c),
};
static unsigned at91_adc_startup_time(unsigned startup_time_min,
unsigned adc_clk_khz)
{
const unsigned startup_lookup[] = {
0, 8, 16, 24,
64, 80, 96, 112,
512, 576, 640, 704,
768, 832, 896, 960
};
unsigned ticks_min, i;
/*
* Since the adc frequency is checked before, there is no reason
* to not meet the startup time constraint.
*/
ticks_min = startup_time_min * adc_clk_khz / 1000;
for (i = 0; i < ARRAY_SIZE(startup_lookup); i++)
if (startup_lookup[i] > ticks_min)
break;
return i;
}
static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq)
{
struct iio_dev *indio_dev = iio_priv_to_dev(st);
unsigned f_per, prescal, startup;
f_per = clk_get_rate(st->per_clk);
prescal = (f_per / (2 * freq)) - 1;
startup = at91_adc_startup_time(st->soc_info.startup_time,
freq / 1000);
at91_adc_writel(st, AT91_SAMA5D2_MR,
AT91_SAMA5D2_MR_TRANSFER(2)
| AT91_SAMA5D2_MR_STARTUP(startup)
| AT91_SAMA5D2_MR_PRESCAL(prescal));
dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n",
freq, startup, prescal);
}
static unsigned at91_adc_get_sample_freq(struct at91_adc_state *st)
{
unsigned f_adc, f_per = clk_get_rate(st->per_clk);
unsigned mr, prescal;
mr = at91_adc_readl(st, AT91_SAMA5D2_MR);
prescal = (mr >> AT91_SAMA5D2_MR_PRESCAL_OFFSET)
& AT91_SAMA5D2_MR_PRESCAL_MAX;
f_adc = f_per / (2 * (prescal + 1));
return f_adc;
}
static irqreturn_t at91_adc_interrupt(int irq, void *private)
{
struct iio_dev *indio = private;
struct at91_adc_state *st = iio_priv(indio);
u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR);
u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR);
if (status & imr) {
st->conversion_value = at91_adc_readl(st, st->chan->address);
st->conversion_done = true;
wake_up_interruptible(&st->wq_data_available);
return IRQ_HANDLED;
}
return IRQ_NONE;
}
static int at91_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct at91_adc_state *st = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&st->lock);
st->chan = chan;
at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel));
at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel));
at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START);
ret = wait_event_interruptible_timeout(st->wq_data_available,
st->conversion_done,
msecs_to_jiffies(1000));
if (ret == 0)
ret = -ETIMEDOUT;
if (ret > 0) {
*val = st->conversion_value;
ret = IIO_VAL_INT;
st->conversion_done = false;
}
at91_adc_writel(st, AT91_SAMA5D2_IDR, BIT(chan->channel));
at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
mutex_unlock(&st->lock);
return ret;
case IIO_CHAN_INFO_SCALE:
*val = st->vref_uv / 1000;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_SAMP_FREQ:
*val = at91_adc_get_sample_freq(st);
return IIO_VAL_INT;
default:
return -EINVAL;
}
}
static int at91_adc_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct at91_adc_state *st = iio_priv(indio_dev);
if (mask != IIO_CHAN_INFO_SAMP_FREQ)
return -EINVAL;
if (val < st->soc_info.min_sample_rate ||
val > st->soc_info.max_sample_rate)
return -EINVAL;
at91_adc_setup_samp_freq(st, val);
return 0;
}
static const struct iio_info at91_adc_info = {
.read_raw = &at91_adc_read_raw,
.write_raw = &at91_adc_write_raw,
.driver_module = THIS_MODULE,
};
static int at91_adc_probe(struct platform_device *pdev)
{
struct iio_dev *indio_dev;
struct at91_adc_state *st;
struct resource *res;
int ret;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
indio_dev->dev.parent = &pdev->dev;
indio_dev->name = dev_name(&pdev->dev);
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &at91_adc_info;
indio_dev->channels = at91_adc_channels;
indio_dev->num_channels = ARRAY_SIZE(at91_adc_channels);
st = iio_priv(indio_dev);
ret = of_property_read_u32(pdev->dev.of_node,
"atmel,min-sample-rate-hz",
&st->soc_info.min_sample_rate);
if (ret) {
dev_err(&pdev->dev,
"invalid or missing value for atmel,min-sample-rate-hz\n");
return ret;
}
ret = of_property_read_u32(pdev->dev.of_node,
"atmel,max-sample-rate-hz",
&st->soc_info.max_sample_rate);
if (ret) {
dev_err(&pdev->dev,
"invalid or missing value for atmel,max-sample-rate-hz\n");
return ret;
}
ret = of_property_read_u32(pdev->dev.of_node, "atmel,startup-time-ms",
&st->soc_info.startup_time);
if (ret) {
dev_err(&pdev->dev,
"invalid or missing value for atmel,startup-time-ms\n");
return ret;
}
init_waitqueue_head(&st->wq_data_available);
mutex_init(&st->lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -EINVAL;
st->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(st->base))
return PTR_ERR(st->base);
st->irq = platform_get_irq(pdev, 0);
if (st->irq <= 0) {
if (!st->irq)
st->irq = -ENXIO;
return st->irq;
}
st->per_clk = devm_clk_get(&pdev->dev, "adc_clk");
if (IS_ERR(st->per_clk))
return PTR_ERR(st->per_clk);
st->reg = devm_regulator_get(&pdev->dev, "vddana");
if (IS_ERR(st->reg))
return PTR_ERR(st->reg);
st->vref = devm_regulator_get(&pdev->dev, "vref");
if (IS_ERR(st->vref))
return PTR_ERR(st->vref);
ret = devm_request_irq(&pdev->dev, st->irq, at91_adc_interrupt, 0,
pdev->dev.driver->name, indio_dev);
if (ret)
return ret;
ret = regulator_enable(st->reg);
if (ret)
return ret;
ret = regulator_enable(st->vref);
if (ret)
goto reg_disable;
st->vref_uv = regulator_get_voltage(st->vref);
if (st->vref_uv <= 0) {
ret = -EINVAL;
goto vref_disable;
}
at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST);
at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff);
at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate);
ret = clk_prepare_enable(st->per_clk);
if (ret)
goto vref_disable;
ret = iio_device_register(indio_dev);
if (ret < 0)
goto per_clk_disable_unprepare;
dev_info(&pdev->dev, "version: %x\n",
readl_relaxed(st->base + AT91_SAMA5D2_VERSION));
return 0;
per_clk_disable_unprepare:
clk_disable_unprepare(st->per_clk);
vref_disable:
regulator_disable(st->vref);
reg_disable:
regulator_disable(st->reg);
return ret;
}
static int at91_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct at91_adc_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
clk_disable_unprepare(st->per_clk);
regulator_disable(st->vref);
regulator_disable(st->reg);
return 0;
}
static const struct of_device_id at91_adc_dt_match[] = {
{
.compatible = "atmel,sama5d2-adc",
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, at91_adc_dt_match);
static struct platform_driver at91_adc_driver = {
.probe = at91_adc_probe,
.remove = at91_adc_remove,
.driver = {
.name = "at91-sama5d2_adc",
.of_match_table = at91_adc_dt_match,
},
};
module_platform_driver(at91_adc_driver)
MODULE_AUTHOR("Ludovic Desroches <ludovic.desroches@atmel.com>");
MODULE_DESCRIPTION("Atmel AT91 SAMA5D2 ADC");
MODULE_LICENSE("GPL v2");

View file

@ -46,7 +46,7 @@ struct axp288_adc_info {
struct regmap *regmap;
};
static const struct iio_chan_spec const axp288_adc_channels[] = {
static const struct iio_chan_spec axp288_adc_channels[] = {
{
.indexed = 1,
.type = IIO_TEMP,

View file

@ -187,26 +187,27 @@ out:
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
}
#define MCP320X_VOLTAGE_CHANNEL_DIFF(num) \
#define MCP320X_VOLTAGE_CHANNEL_DIFF(chan1, chan2) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (num * 2), \
.channel2 = (num * 2 + 1), \
.address = (num * 2), \
.channel = (chan1), \
.channel2 = (chan2), \
.address = (chan1), \
.differential = 1, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
}
static const struct iio_chan_spec mcp3201_channels[] = {
MCP320X_VOLTAGE_CHANNEL_DIFF(0),
MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
};
static const struct iio_chan_spec mcp3202_channels[] = {
MCP320X_VOLTAGE_CHANNEL(0),
MCP320X_VOLTAGE_CHANNEL(1),
MCP320X_VOLTAGE_CHANNEL_DIFF(0),
MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0),
};
static const struct iio_chan_spec mcp3204_channels[] = {
@ -214,8 +215,10 @@ static const struct iio_chan_spec mcp3204_channels[] = {
MCP320X_VOLTAGE_CHANNEL(1),
MCP320X_VOLTAGE_CHANNEL(2),
MCP320X_VOLTAGE_CHANNEL(3),
MCP320X_VOLTAGE_CHANNEL_DIFF(0),
MCP320X_VOLTAGE_CHANNEL_DIFF(1),
MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0),
MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3),
MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2),
};
static const struct iio_chan_spec mcp3208_channels[] = {
@ -227,10 +230,14 @@ static const struct iio_chan_spec mcp3208_channels[] = {
MCP320X_VOLTAGE_CHANNEL(5),
MCP320X_VOLTAGE_CHANNEL(6),
MCP320X_VOLTAGE_CHANNEL(7),
MCP320X_VOLTAGE_CHANNEL_DIFF(0),
MCP320X_VOLTAGE_CHANNEL_DIFF(1),
MCP320X_VOLTAGE_CHANNEL_DIFF(2),
MCP320X_VOLTAGE_CHANNEL_DIFF(3),
MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0),
MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3),
MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2),
MCP320X_VOLTAGE_CHANNEL_DIFF(4, 5),
MCP320X_VOLTAGE_CHANNEL_DIFF(5, 4),
MCP320X_VOLTAGE_CHANNEL_DIFF(6, 7),
MCP320X_VOLTAGE_CHANNEL_DIFF(7, 6),
};
static const struct iio_info mcp320x_info = {

View file

@ -1,11 +1,12 @@
/*
* mcp3422.c - driver for the Microchip mcp3422/3/4/6/7/8 chip family
* mcp3422.c - driver for the Microchip mcp3421/2/3/4/5/6/7/8 chip family
*
* Copyright (C) 2013, Angelo Compagnucci
* Author: Angelo Compagnucci <angelo.compagnucci@gmail.com>
*
* Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/22088b.pdf
* http://ww1.microchip.com/downloads/en/DeviceDoc/22226a.pdf
* http://ww1.microchip.com/downloads/en/DeviceDoc/22072b.pdf
*
* This driver exports the value of analog input voltage to sysfs, the
* voltage unit is nV.
@ -357,6 +358,7 @@ static int mcp3422_probe(struct i2c_client *client,
switch (adc->id) {
case 1:
case 5:
indio_dev->channels = mcp3421_channels;
indio_dev->num_channels = ARRAY_SIZE(mcp3421_channels);
break;
@ -395,6 +397,7 @@ static const struct i2c_device_id mcp3422_id[] = {
{ "mcp3422", 2 },
{ "mcp3423", 3 },
{ "mcp3424", 4 },
{ "mcp3425", 5 },
{ "mcp3426", 6 },
{ "mcp3427", 7 },
{ "mcp3428", 8 },
@ -421,5 +424,5 @@ static struct i2c_driver mcp3422_driver = {
module_i2c_driver(mcp3422_driver);
MODULE_AUTHOR("Angelo Compagnucci <angelo.compagnucci@gmail.com>");
MODULE_DESCRIPTION("Microchip mcp3422/3/4/6/7/8 driver");
MODULE_DESCRIPTION("Microchip mcp3421/2/3/4/5/6/7/8 driver");
MODULE_LICENSE("GPL v2");

View file

@ -4,6 +4,19 @@
menu "Chemical Sensors"
config ATLAS_PH_SENSOR
tristate "Atlas Scientific OEM pH-SM sensor"
depends on I2C
select REGMAP_I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say Y here to build I2C interface support for the Atlas
Scientific OEM pH-SM sensor.
To compile this driver as module, choose M here: the
module will be called atlas-ph-sensor.
config IAQCORE
tristate "AMS iAQ-Core VOC sensors"
depends on I2C

Some files were not shown because too many files have changed in this diff Show more