提交 25a0dc4b 编写于 作者: L Linus Torvalds

Merge tag 'staging-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging

Pull staging and IIO driver updates from Greg KH:
 "Here is the big Staging and IIO driver update for 4.8-rc1.

  We ended up adding more code than removing, again, but it's not all
  that bad.  Lots of cleanups all over the staging tree, and new IIO
  drivers, full details in the shortlog.

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'staging-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (417 commits)
  drivers:iio:accel:mma8452: removed unwanted return statements
  drivers:iio:accel:mma8452: added cleanup provision in case of failure.
  iio: Add iio.git tree to MAINTAINERS
  iio:st_pressure: clean useless static channel initializers
  iio:st_pressure:lps22hb: temperature support
  iio:st_pressure:lps22hb: open drain support
  iio:st_pressure: temperature triggered buffering
  iio:st_pressure: document sampling gains
  iio:st_pressure: align storagebits on power of 2
  iio:st_sensors: align on storagebits boundaries
  staging:iio:lis3l02dq drop separate driver
  iio: accel: st_accel: Add lis3l02dq support
  iio: adc: add missing of_node references to iio_dev
  iio: adc: ti-ads1015: add indio_dev->dev.of_node reference
  iio: potentiometer: Fix typo in Kconfig
  iio: potentiometer: mcp4531: Add device tree binding
  iio: potentiometer: mcp4531: Add device tree binding documentation
  iio: potentiometer: mcp4531: Add support for MCP454x, MCP456x, MCP464x and MCP466x
  iio:imu:mpu6050: icm20608 initial support
  iio: adc: max1363: Add device tree binding
  ...
...@@ -11,6 +11,7 @@ Aaron Durbin <adurbin@google.com> ...@@ -11,6 +11,7 @@ Aaron Durbin <adurbin@google.com>
Adam Oldham <oldhamca@gmail.com> Adam Oldham <oldhamca@gmail.com>
Adam Radford <aradford@gmail.com> Adam Radford <aradford@gmail.com>
Adrian Bunk <bunk@stusta.de> Adrian Bunk <bunk@stusta.de>
Adriana Reus <adi.reus@gmail.com> <adriana.reus@intel.com>
Alan Cox <alan@lxorguk.ukuu.org.uk> Alan Cox <alan@lxorguk.ukuu.org.uk>
Alan Cox <root@hraefn.swansea.linux.org.uk> Alan Cox <root@hraefn.swansea.linux.org.uk>
Aleksey Gorelov <aleksey_gorelov@phoenix.com> Aleksey Gorelov <aleksey_gorelov@phoenix.com>
...@@ -94,6 +95,8 @@ Linas Vepstas <linas@austin.ibm.com> ...@@ -94,6 +95,8 @@ Linas Vepstas <linas@austin.ibm.com>
Mark Brown <broonie@sirena.org.uk> Mark Brown <broonie@sirena.org.uk>
Matthieu CASTET <castet.matthieu@free.fr> Matthieu CASTET <castet.matthieu@free.fr>
Mauro Carvalho Chehab <mchehab@kernel.org> <maurochehab@gmail.com> <mchehab@infradead.org> <mchehab@redhat.com> <m.chehab@samsung.com> <mchehab@osg.samsung.com> <mchehab@s-opensource.com> Mauro Carvalho Chehab <mchehab@kernel.org> <maurochehab@gmail.com> <mchehab@infradead.org> <mchehab@redhat.com> <m.chehab@samsung.com> <mchehab@osg.samsung.com> <mchehab@s-opensource.com>
Matt Ranostay <mranostay@gmail.com> Matthew Ranostay <mranostay@embeddedalley.com>
Matt Ranostay <mranostay@gmail.com> <matt.ranostay@intel.com>
Mayuresh Janorkar <mayur@ti.com> Mayuresh Janorkar <mayur@ti.com>
Michael Buesch <m@bues.ch> Michael Buesch <m@bues.ch>
Michel Dänzer <michel@tungstengraphics.com> Michel Dänzer <michel@tungstengraphics.com>
......
...@@ -19,3 +19,16 @@ KernelVersion: 4.4 ...@@ -19,3 +19,16 @@ KernelVersion: 4.4
Description: Description:
High resolution timers directory. Creating a directory here High resolution timers directory. Creating a directory here
will result in creating a hrtimer trigger in the IIO subsystem. will result in creating a hrtimer trigger in the IIO subsystem.
What: /config/iio/devices
Date: April 2016
KernelVersion: 4.7
Description:
Industrial IO software devices directory.
What: /config/iio/devices/dummy
Date: April 2016
KernelVersion: 4.7
Description:
Dummy IIO devices directory. Creating a directory here will result
in creating a dummy IIO device in the IIO subystem.
...@@ -32,6 +32,13 @@ Description: ...@@ -32,6 +32,13 @@ Description:
Description of the physical chip / device for device X. Description of the physical chip / device for device X.
Typically a part number. Typically a part number.
What: /sys/bus/iio/devices/iio:deviceX/timestamp_clock
KernelVersion: 4.5
Contact: linux-iio@vger.kernel.org
Description:
String identifying current posix clock used to timestamp
buffered samples and events for device X.
What: /sys/bus/iio/devices/iio:deviceX/sampling_frequency What: /sys/bus/iio/devices/iio:deviceX/sampling_frequency
What: /sys/bus/iio/devices/iio:deviceX/buffer/sampling_frequency What: /sys/bus/iio/devices/iio:deviceX/buffer/sampling_frequency
What: /sys/bus/iio/devices/triggerX/sampling_frequency What: /sys/bus/iio/devices/triggerX/sampling_frequency
...@@ -1565,3 +1572,10 @@ Description: ...@@ -1565,3 +1572,10 @@ Description:
* X is in the plane of the propellers, perpendicular to Y axis, * X is in the plane of the propellers, perpendicular to Y axis,
and positive towards the starboard side of the UAV ; and positive towards the starboard side of the UAV ;
* Z is perpendicular to propellers plane and positive upwards. * Z is perpendicular to propellers plane and positive upwards.
What: /sys/bus/iio/devices/iio:deviceX/in_electricalconductivity_raw
KernelVersion: 4.8
Contact: linux-iio@vger.kernel.org
Description:
Raw (unscaled no offset etc.) electric conductivity reading that
can be processed to siemens per meter.
What: /sys/bus/iio/devices/iio:deviceX/tia_resistanceY What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_raw
/sys/bus/iio/devices/iio:deviceX/tia_capacitanceY Date: May 2016
Date: December 2015
KernelVersion:
Contact: Andrew F. Davis <afd@ti.com>
Description:
Get and set the resistance and the capacitance settings for the
Transimpedance Amplifier. Y is 1 for Rf1 and Cf1, Y is 2 for
Rf2 and Cf2 values.
What: /sys/bus/iio/devices/iio:deviceX/tia_separate_en
Date: December 2015
KernelVersion:
Contact: Andrew F. Davis <afd@ti.com>
Description:
Enable or disable separate settings for the TransImpedance
Amplifier above, when disabled both values are set by the
first channel.
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_ledY_raw
/sys/bus/iio/devices/iio:deviceX/in_intensity_ledY_ambient_raw
Date: December 2015
KernelVersion: KernelVersion:
Contact: Andrew F. Davis <afd@ti.com> Contact: Andrew F. Davis <afd@ti.com>
Description: Description:
Get measured values from the ADC for these stages. Y is the Get measured values from the ADC for these stages. Y is the
specific LED number. The values are expressed in 24-bit twos specific stage number corresponding to datasheet stage names
complement. as follows:
1 -> LED2
2 -> ALED2/LED3
3 -> LED1
4 -> ALED1/LED4
Note that channels 5 and 6 represent LED2-ALED2 and LED1-ALED1
respectively which simply helper channels containing the
calculated difference in the value of stage 1 - 2 and 3 - 4.
The values are expressed in 24-bit twos complement.
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_ledY-ledY_ambient_raw What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_offset
Date: December 2015 Date: May 2016
KernelVersion: KernelVersion:
Contact: Andrew F. Davis <afd@ti.com> Contact: Andrew F. Davis <afd@ti.com>
Description: Description:
Get differential values from the ADC for these stages. Y is the Get and set the offset cancellation DAC setting for these
specific LED number. The values are expressed in 24-bit twos stages. The values are expressed in 5-bit sign-magnitude.
complement for the specified LEDs.
What: /sys/bus/iio/devices/iio:deviceX/out_current_ledY_offset What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_resistance
/sys/bus/iio/devices/iio:deviceX/out_current_ledY_ambient_offset What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_capacitance
Date: December 2015 Date: May 2016
KernelVersion: KernelVersion:
Contact: Andrew F. Davis <afd@ti.com> Contact: Andrew F. Davis <afd@ti.com>
Description: Description:
Get and set the offset cancellation DAC setting for these Get and set the resistance and the capacitance settings for the
stages. The values are expressed in 5-bit sign-magnitude. Transimpedance Amplifier during the associated stage.
What: /sys/bus/iio/devices/iio:deviceX/out_current_ledY_raw What: /sys/bus/iio/devices/iio:deviceX/out_currentY_raw
Date: December 2015 Date: May 2016
KernelVersion: KernelVersion:
Contact: Andrew F. Davis <afd@ti.com> Contact: Andrew F. Davis <afd@ti.com>
Description: Description:
Get and set the LED current for the specified LED. Y is the Get and set the LED current for the specified LED active during
specific LED number. this stage. Y is the specific stage number.
...@@ -594,7 +594,7 @@ ...@@ -594,7 +594,7 @@
irqreturn_t sensor_iio_pollfunc(int irq, void *p) irqreturn_t sensor_iio_pollfunc(int irq, void *p)
{ {
pf->timestamp = iio_get_time_ns(); pf->timestamp = iio_get_time_ns((struct indio_dev *)p);
return IRQ_WAKE_THREAD; return IRQ_WAKE_THREAD;
} }
......
...@@ -56,6 +56,70 @@ maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator ...@@ -56,6 +56,70 @@ maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator
maxim,max1237 Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs maxim,max1237 Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs
maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface
mc,rv3029c2 Real Time Clock Module with I2C-Bus mc,rv3029c2 Real Time Clock Module with I2C-Bus
microchip,mcp4531-502 Microchip 7-bit Single I2C Digital Potentiometer (5k)
microchip,mcp4531-103 Microchip 7-bit Single I2C Digital Potentiometer (10k)
microchip,mcp4531-503 Microchip 7-bit Single I2C Digital Potentiometer (50k)
microchip,mcp4531-104 Microchip 7-bit Single I2C Digital Potentiometer (100k)
microchip,mcp4532-502 Microchip 7-bit Single I2C Digital Potentiometer (5k)
microchip,mcp4532-103 Microchip 7-bit Single I2C Digital Potentiometer (10k)
microchip,mcp4532-503 Microchip 7-bit Single I2C Digital Potentiometer (50k)
microchip,mcp4532-104 Microchip 7-bit Single I2C Digital Potentiometer (100k)
microchip,mcp4541-502 Microchip 7-bit Single I2C Digital Potentiometer with NV Memory (5k)
microchip,mcp4541-103 Microchip 7-bit Single I2C Digital Potentiometer with NV Memory (10k)
microchip,mcp4541-503 Microchip 7-bit Single I2C Digital Potentiometer with NV Memory (50k)
microchip,mcp4541-104 Microchip 7-bit Single I2C Digital Potentiometer with NV Memory (100k)
microchip,mcp4542-502 Microchip 7-bit Single I2C Digital Potentiometer with NV Memory (5k)
microchip,mcp4542-103 Microchip 7-bit Single I2C Digital Potentiometer with NV Memory (10k)
microchip,mcp4542-503 Microchip 7-bit Single I2C Digital Potentiometer with NV Memory (50k)
microchip,mcp4542-104 Microchip 7-bit Single I2C Digital Potentiometer with NV Memory (100k)
microchip,mcp4551-502 Microchip 8-bit Single I2C Digital Potentiometer (5k)
microchip,mcp4551-103 Microchip 8-bit Single I2C Digital Potentiometer (10k)
microchip,mcp4551-503 Microchip 8-bit Single I2C Digital Potentiometer (50k)
microchip,mcp4551-104 Microchip 8-bit Single I2C Digital Potentiometer (100k)
microchip,mcp4552-502 Microchip 8-bit Single I2C Digital Potentiometer (5k)
microchip,mcp4552-103 Microchip 8-bit Single I2C Digital Potentiometer (10k)
microchip,mcp4552-503 Microchip 8-bit Single I2C Digital Potentiometer (50k)
microchip,mcp4552-104 Microchip 8-bit Single I2C Digital Potentiometer (100k)
microchip,mcp4561-502 Microchip 8-bit Single I2C Digital Potentiometer with NV Memory (5k)
microchip,mcp4561-103 Microchip 8-bit Single I2C Digital Potentiometer with NV Memory (10k)
microchip,mcp4561-503 Microchip 8-bit Single I2C Digital Potentiometer with NV Memory (50k)
microchip,mcp4561-104 Microchip 8-bit Single I2C Digital Potentiometer with NV Memory (100k)
microchip,mcp4562-502 Microchip 8-bit Single I2C Digital Potentiometer with NV Memory (5k)
microchip,mcp4562-103 Microchip 8-bit Single I2C Digital Potentiometer with NV Memory (10k)
microchip,mcp4562-503 Microchip 8-bit Single I2C Digital Potentiometer with NV Memory (50k)
microchip,mcp4562-104 Microchip 8-bit Single I2C Digital Potentiometer with NV Memory (100k)
microchip,mcp4631-502 Microchip 7-bit Dual I2C Digital Potentiometer (5k)
microchip,mcp4631-103 Microchip 7-bit Dual I2C Digital Potentiometer (10k)
microchip,mcp4631-503 Microchip 7-bit Dual I2C Digital Potentiometer (50k)
microchip,mcp4631-104 Microchip 7-bit Dual I2C Digital Potentiometer (100k)
microchip,mcp4632-502 Microchip 7-bit Dual I2C Digital Potentiometer (5k)
microchip,mcp4632-103 Microchip 7-bit Dual I2C Digital Potentiometer (10k)
microchip,mcp4632-503 Microchip 7-bit Dual I2C Digital Potentiometer (50k)
microchip,mcp4632-104 Microchip 7-bit Dual I2C Digital Potentiometer (100k)
microchip,mcp4641-502 Microchip 7-bit Dual I2C Digital Potentiometer with NV Memory (5k)
microchip,mcp4641-103 Microchip 7-bit Dual I2C Digital Potentiometer with NV Memory (10k)
microchip,mcp4641-503 Microchip 7-bit Dual I2C Digital Potentiometer with NV Memory (50k)
microchip,mcp4641-104 Microchip 7-bit Dual I2C Digital Potentiometer with NV Memory (100k)
microchip,mcp4642-502 Microchip 7-bit Dual I2C Digital Potentiometer with NV Memory (5k)
microchip,mcp4642-103 Microchip 7-bit Dual I2C Digital Potentiometer with NV Memory (10k)
microchip,mcp4642-503 Microchip 7-bit Dual I2C Digital Potentiometer with NV Memory (50k)
microchip,mcp4642-104 Microchip 7-bit Dual I2C Digital Potentiometer with NV Memory (100k)
microchip,mcp4651-502 Microchip 8-bit Dual I2C Digital Potentiometer (5k)
microchip,mcp4651-103 Microchip 8-bit Dual I2C Digital Potentiometer (10k)
microchip,mcp4651-503 Microchip 8-bit Dual I2C Digital Potentiometer (50k)
microchip,mcp4651-104 Microchip 8-bit Dual I2C Digital Potentiometer (100k)
microchip,mcp4652-502 Microchip 8-bit Dual I2C Digital Potentiometer (5k)
microchip,mcp4652-103 Microchip 8-bit Dual I2C Digital Potentiometer (10k)
microchip,mcp4652-503 Microchip 8-bit Dual I2C Digital Potentiometer (50k)
microchip,mcp4652-104 Microchip 8-bit Dual I2C Digital Potentiometer (100k)
microchip,mcp4661-502 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (5k)
microchip,mcp4661-103 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (10k)
microchip,mcp4661-503 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (50k)
microchip,mcp4661-104 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (100k)
microchip,mcp4662-502 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (5k)
microchip,mcp4662-103 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (10k)
microchip,mcp4662-503 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (50k)
microchip,mcp4662-104 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (100k)
national,lm63 Temperature sensor with integrated fan control national,lm63 Temperature sensor with integrated fan control
national,lm75 I2C TEMP SENSOR national,lm75 I2C TEMP SENSOR
national,lm80 Serial Interface ACPI-Compatible Microprocessor System Hardware Monitor national,lm80 Serial Interface ACPI-Compatible Microprocessor System Hardware Monitor
......
* Broadcom's IPROC Static ADC controller
Broadcom iProc ADC controller has 8 channels 10bit ADC.
Allows user to convert analog input voltage values to digital.
Required properties:
- compatible: Must be "brcm,iproc-static-adc"
- adc-syscon: Handler of syscon node defining physical base address of the
controller and length of memory mapped region.
- #io-channel-cells = <1>; As ADC has multiple outputs
refer to Documentation/devicetree/bindings/iio/iio-bindings.txt for details.
- io-channel-ranges:
refer to Documentation/devicetree/bindings/iio/iio-bindings.txt for details.
- clocks: Clock used for this block.
- clock-names: Clock name should be given as tsc_clk.
- interrupts: interrupt line number.
For example:
ts_adc_syscon: ts_adc_syscon@180a6000 {
compatible = "brcm,iproc-ts-adc-syscon","syscon";
reg = <0x180a6000 0xc30>;
};
adc: adc@180a6000 {
compatible = "brcm,iproc-static-adc";
adc-syscon = <&ts_adc_syscon>;
#io-channel-cells = <1>;
io-channel-ranges;
clocks = <&asiu_clks BCM_CYGNUS_ASIU_ADC_CLK>;
clock-names = "tsc_clk";
interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
* Maxim 1x3x/136x/116xx Analog to Digital Converter (ADC)
The node for this driver must be a child node of a I2C controller, hence
all mandatory properties for your controller must be specified. See directory:
Documentation/devicetree/bindings/i2c
for more details.
Required properties:
- compatible: Should be one of
"maxim,max1361"
"maxim,max1362"
"maxim,max1363"
"maxim,max1364"
"maxim,max1036"
"maxim,max1037"
"maxim,max1038"
"maxim,max1039"
"maxim,max1136"
"maxim,max1137"
"maxim,max1138"
"maxim,max1139"
"maxim,max1236"
"maxim,max1237"
"maxim,max1238"
"maxim,max1239"
"maxim,max11600"
"maxim,max11601"
"maxim,max11602"
"maxim,max11603"
"maxim,max11604"
"maxim,max11605"
"maxim,max11606"
"maxim,max11607"
"maxim,max11608"
"maxim,max11609"
"maxim,max11610"
"maxim,max11611"
"maxim,max11612"
"maxim,max11613"
"maxim,max11614"
"maxim,max11615"
"maxim,max11616"
"maxim,max11617"
"maxim,max11644"
"maxim,max11645"
"maxim,max11646"
"maxim,max11647"
- reg: Should contain the ADC I2C address
Optional properties:
- vcc-supply: phandle to the regulator that provides power to the ADC.
- vref-supply: phandle to the regulator for ADC reference voltage.
- interrupts: IRQ line for the ADC. If not used the driver will use
polling.
Example:
adc: max11644@36 {
compatible = "maxim,max11644";
reg = <0x36>;
vref-supply = <&adc_vref>;
};
* Atlas Scientific EC-SM OEM sensor
http://www.atlas-scientific.com/_files/_datasheets/_oem/EC_oem_datasheet.pdf
Required properties:
- compatible: must be "atlas,ec-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@64 {
compatible = "atlas,ec-sm";
reg = <0x64>;
interrupt-parent = <&gpio1>;
interrupts = <16 2>;
};
* Analog Device AD5755 IIO Multi-Channel DAC Linux Driver
Required properties:
- compatible: Has to contain one of the following:
adi,ad5755
adi,ad5755-1
adi,ad5757
adi,ad5735
adi,ad5737
- reg: spi chip select number for the device
- spi-cpha or spi-cpol: is the only modes that is supported
Recommended properties:
- spi-max-frequency: Definition as per
Documentation/devicetree/bindings/spi/spi-bus.txt
Optional properties:
See include/dt-bindings/iio/ad5755.h
- adi,ext-dc-dc-compenstation-resistor: boolean set if the hardware have an
external resistor and thereby bypasses
the internal compensation resistor.
- adi,dc-dc-phase:
Valid values for DC DC Phase control is:
0: All dc-to-dc converters clock on the same edge.
1: Channel A and Channel B clock on the same edge,
Channel C and Channel D clock on opposite edges.
2: Channel A and Channel C clock on the same edge,
Channel B and Channel D clock on opposite edges.
3: Channel A, Channel B, Channel C, and Channel D
clock 90 degrees out of phase from each other.
- adi,dc-dc-freq-hz:
Valid values for DC DC frequency is [Hz]:
250000
410000
650000
- adi,dc-dc-max-microvolt:
Valid values for the maximum allowed Vboost voltage supplied by
the dc-to-dc converter is:
23000000
24500000
27000000
29500000
Optional for every channel:
- adi,mode:
Valid values for DAC modes is:
0: 0 V to 5 V voltage range.
1: 0 V to 10 V voltage range.
2: Plus minus 5 V voltage range.
3: Plus minus 10 V voltage range.
4: 4 mA to 20 mA current range.
5: 0 mA to 20 mA current range.
6: 0 mA to 24 mA current range.
- adi,ext-current-sense-resistor: boolean set if the hardware a external
current sense resistor.
- adi,enable-voltage-overrange: boolean enable voltage overrange
- adi,slew: Array of slewrate settings should contain 3 fields:
1: Should be either 0 or 1 in order to enable or disable slewrate.
2: Slew rate settings:
Valid values for the slew rate update frequency:
64000
32000
16000
8000
4000
2000
1000
500
250
125
64
32
16
8
4
0
3: Slew step size:
Valid values for the step size LSBs:
1
2
4
16
32
64
128
256
Example:
dac@0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "adi,ad5755";
reg = <0>;
spi-max-frequency = <1000000>;
spi-cpha;
adi,dc-dc-phase = <0>;
adi,dc-dc-freq-hz = <410000>;
adi,dc-dc-max-microvolt = <23000000>;
channel@0 {
reg = <0>;
adi,mode = <4>;
adi,ext-current-sense-resistor;
adi,slew = <0 64000 1>;
};
channel@1 {
reg = <1>;
adi,mode = <4>;
adi,ext-current-sense-resistor;
adi,slew = <0 64000 1>;
};
channel@2 {
reg = <2>;
adi,mode = <4>;
adi,ext-current-sense-resistor;
adi,slew = <0 64000 1>;
};
channel@3 {
reg = <3>;
adi,mode = <4>;
adi,ext-current-sense-resistor;
adi,slew = <0 64000 1>;
};
};
BMP085/BMP18x digital pressure sensors BMP085/BMP18x/BMP28x digital pressure sensors
Required properties: Required properties:
- compatible: bosch,bmp085 - compatible: must be one of:
"bosch,bmp085"
"bosch,bmp180"
"bosch,bmp280"
"bosch,bme280"
Optional properties: Optional properties:
- chip-id: configurable chip id for non-default chip revisions - chip-id: configurable chip id for non-default chip revisions
...@@ -10,6 +14,10 @@ Optional properties: ...@@ -10,6 +14,10 @@ Optional properties:
value range is 0-3 with rising sensitivity. value range is 0-3 with rising sensitivity.
- interrupt-parent: should be the phandle for the interrupt controller - interrupt-parent: should be the phandle for the interrupt controller
- interrupts: interrupt mapping for IRQ - interrupts: interrupt mapping for IRQ
- reset-gpios: a GPIO line handling reset of the sensor: as the line is
active low, it should be marked GPIO_ACTIVE_LOW (see gpio/gpio.txt)
- vddd-supply: digital voltage regulator (see regulator/regulator.txt)
- vdda-supply: analog voltage regulator (see regulator/regulator.txt)
Example: Example:
...@@ -21,4 +29,7 @@ pressure@77 { ...@@ -21,4 +29,7 @@ pressure@77 {
default-oversampling = <2>; default-oversampling = <2>;
interrupt-parent = <&gpio0>; interrupt-parent = <&gpio0>;
interrupts = <25 IRQ_TYPE_EDGE_RISING>; interrupts = <25 IRQ_TYPE_EDGE_RISING>;
reset-gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
vddd-supply = <&foo>;
vdda-supply = <&bar>;
}; };
...@@ -64,3 +64,4 @@ Pressure sensors: ...@@ -64,3 +64,4 @@ Pressure sensors:
- st,lps001wp-press - st,lps001wp-press
- st,lps25h-press - st,lps25h-press
- st,lps331ap-press - st,lps331ap-press
- st,lps22hb-press
...@@ -5788,7 +5788,9 @@ R: Hartmut Knaack <knaack.h@gmx.de> ...@@ -5788,7 +5788,9 @@ R: Hartmut Knaack <knaack.h@gmx.de>
R: Lars-Peter Clausen <lars@metafoo.de> R: Lars-Peter Clausen <lars@metafoo.de>
R: Peter Meerwald-Stadler <pmeerw@pmeerw.net> R: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
L: linux-iio@vger.kernel.org L: linux-iio@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/iio/
F: drivers/iio/ F: drivers/iio/
F: drivers/staging/iio/ F: drivers/staging/iio/
F: include/linux/iio/ F: include/linux/iio/
...@@ -10861,6 +10863,7 @@ STAGING - INDUSTRIAL IO ...@@ -10861,6 +10863,7 @@ STAGING - INDUSTRIAL IO
M: Jonathan Cameron <jic23@kernel.org> M: Jonathan Cameron <jic23@kernel.org>
L: linux-iio@vger.kernel.org L: linux-iio@vger.kernel.org
S: Odd Fixes S: Odd Fixes
F: Documentation/devicetree/bindings/staging/iio/
F: drivers/staging/iio/ F: drivers/staging/iio/
STAGING - LIRC (LINUX INFRARED REMOTE CONTROL) DRIVERS STAGING - LIRC (LINUX INFRARED REMOTE CONTROL) DRIVERS
......
...@@ -46,6 +46,14 @@ config IIO_CONSUMERS_PER_TRIGGER ...@@ -46,6 +46,14 @@ config IIO_CONSUMERS_PER_TRIGGER
This value controls the maximum number of consumers that a This value controls the maximum number of consumers that a
given trigger may handle. Default is 2. given trigger may handle. Default is 2.
config IIO_SW_DEVICE
tristate "Enable software IIO device support"
select IIO_CONFIGFS
help
Provides IIO core support for software devices. A software
device can be created via configfs or directly by a driver
using the API provided.
config IIO_SW_TRIGGER config IIO_SW_TRIGGER
tristate "Enable software triggers support" tristate "Enable software triggers support"
select IIO_CONFIGFS select IIO_CONFIGFS
......
...@@ -8,6 +8,7 @@ industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o ...@@ -8,6 +8,7 @@ industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o
industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o
obj-$(CONFIG_IIO_CONFIGFS) += industrialio-configfs.o obj-$(CONFIG_IIO_CONFIGFS) += industrialio-configfs.o
obj-$(CONFIG_IIO_SW_DEVICE) += industrialio-sw-device.o
obj-$(CONFIG_IIO_SW_TRIGGER) += industrialio-sw-trigger.o obj-$(CONFIG_IIO_SW_TRIGGER) += industrialio-sw-trigger.o
obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o
......
...@@ -17,6 +17,16 @@ config BMA180 ...@@ -17,6 +17,16 @@ config BMA180
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called bma180. module will be called bma180.
config BMA220
tristate "Bosch BMA220 3-Axis Accelerometer Driver"
depends on SPI
help
Say yes here to add support for the Bosch BMA220 triaxial
acceleration sensor.
To compile this driver as a module, choose M here: the
module will be called bma220_spi.
config BMC150_ACCEL config BMC150_ACCEL
tristate "Bosch BMC150 Accelerometer Driver" tristate "Bosch BMC150 Accelerometer Driver"
select IIO_BUFFER select IIO_BUFFER
...@@ -136,13 +146,23 @@ config MMA7455_SPI ...@@ -136,13 +146,23 @@ config MMA7455_SPI
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called mma7455_spi. will be called mma7455_spi.
config MMA7660
tristate "Freescale MMA7660FC 3-Axis Accelerometer Driver"
depends on I2C
help
Say yes here to get support for the Freescale MMA7660FC 3-Axis
accelerometer.
Choosing M will build the driver as a module. If so, the module
will be called mma7660.
config MMA8452 config MMA8452
tristate "Freescale MMA8452Q and similar Accelerometers Driver" tristate "Freescale / NXP MMA8452Q and similar Accelerometers Driver"
depends on I2C depends on I2C
select IIO_BUFFER select IIO_BUFFER
select IIO_TRIGGERED_BUFFER select IIO_TRIGGERED_BUFFER
help help
Say yes here to build support for the following Freescale 3-axis Say yes here to build support for the following Freescale / NXP 3-axis
accelerometers: MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC, accelerometers: MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC,
FXLS8471Q. FXLS8471Q.
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
# When adding new entries keep the list in alphabetical order # When adding new entries keep the list in alphabetical order
obj-$(CONFIG_BMA180) += bma180.o obj-$(CONFIG_BMA180) += bma180.o
obj-$(CONFIG_BMA220) += bma220_spi.o
obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
...@@ -15,6 +16,8 @@ obj-$(CONFIG_MMA7455) += mma7455_core.o ...@@ -15,6 +16,8 @@ obj-$(CONFIG_MMA7455) += mma7455_core.o
obj-$(CONFIG_MMA7455_I2C) += mma7455_i2c.o obj-$(CONFIG_MMA7455_I2C) += mma7455_i2c.o
obj-$(CONFIG_MMA7455_SPI) += mma7455_spi.o obj-$(CONFIG_MMA7455_SPI) += mma7455_spi.o
obj-$(CONFIG_MMA7660) += mma7660.o
obj-$(CONFIG_MMA8452) += mma8452.o obj-$(CONFIG_MMA8452) += mma8452.o
obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o
......
...@@ -654,7 +654,7 @@ static irqreturn_t bma180_trigger_handler(int irq, void *p) ...@@ -654,7 +654,7 @@ static irqreturn_t bma180_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p; struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev; struct iio_dev *indio_dev = pf->indio_dev;
struct bma180_data *data = iio_priv(indio_dev); struct bma180_data *data = iio_priv(indio_dev);
int64_t time_ns = iio_get_time_ns(); s64 time_ns = iio_get_time_ns(indio_dev);
int bit, ret, i = 0; int bit, ret, i = 0;
mutex_lock(&data->mutex); mutex_lock(&data->mutex);
......
/**
* BMA220 Digital triaxial acceleration sensor driver
*
* Copyright (c) 2016, Intel Corporation.
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*/
#include <linux/acpi.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/spi/spi.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#define BMA220_REG_ID 0x00
#define BMA220_REG_ACCEL_X 0x02
#define BMA220_REG_ACCEL_Y 0x03
#define BMA220_REG_ACCEL_Z 0x04
#define BMA220_REG_RANGE 0x11
#define BMA220_REG_SUSPEND 0x18
#define BMA220_CHIP_ID 0xDD
#define BMA220_READ_MASK 0x80
#define BMA220_RANGE_MASK 0x03
#define BMA220_DATA_SHIFT 2
#define BMA220_SUSPEND_SLEEP 0xFF
#define BMA220_SUSPEND_WAKE 0x00
#define BMA220_DEVICE_NAME "bma220"
#define BMA220_SCALE_AVAILABLE "0.623 1.248 2.491 4.983"
#define BMA220_ACCEL_CHANNEL(index, reg, axis) { \
.type = IIO_ACCEL, \
.address = reg, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.scan_index = index, \
.scan_type = { \
.sign = 's', \
.realbits = 6, \
.storagebits = 8, \
.shift = BMA220_DATA_SHIFT, \
.endianness = IIO_CPU, \
}, \
}
enum bma220_axis {
AXIS_X,
AXIS_Y,
AXIS_Z,
};
static IIO_CONST_ATTR(in_accel_scale_available, BMA220_SCALE_AVAILABLE);
static struct attribute *bma220_attributes[] = {
&iio_const_attr_in_accel_scale_available.dev_attr.attr,
NULL,
};
static const struct attribute_group bma220_attribute_group = {
.attrs = bma220_attributes,
};
static const int bma220_scale_table[][4] = {
{0, 623000}, {1, 248000}, {2, 491000}, {4, 983000}
};
struct bma220_data {
struct spi_device *spi_device;
struct mutex lock;
s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 8x8 timestamp */
u8 tx_buf[2] ____cacheline_aligned;
};
static const struct iio_chan_spec bma220_channels[] = {
BMA220_ACCEL_CHANNEL(0, BMA220_REG_ACCEL_X, X),
BMA220_ACCEL_CHANNEL(1, BMA220_REG_ACCEL_Y, Y),
BMA220_ACCEL_CHANNEL(2, BMA220_REG_ACCEL_Z, Z),
IIO_CHAN_SOFT_TIMESTAMP(3),
};
static inline int bma220_read_reg(struct spi_device *spi, u8 reg)
{
return spi_w8r8(spi, reg | BMA220_READ_MASK);
}
static const unsigned long bma220_accel_scan_masks[] = {
BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
0
};
static irqreturn_t bma220_trigger_handler(int irq, void *p)
{
int ret;
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bma220_data *data = iio_priv(indio_dev);
struct spi_device *spi = data->spi_device;
mutex_lock(&data->lock);
data->tx_buf[0] = BMA220_REG_ACCEL_X | BMA220_READ_MASK;
ret = spi_write_then_read(spi, data->tx_buf, 1, data->buffer,
ARRAY_SIZE(bma220_channels) - 1);
if (ret < 0)
goto err;
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
pf->timestamp);
err:
mutex_unlock(&data->lock);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
static int bma220_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
int ret;
u8 range_idx;
struct bma220_data *data = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
ret = bma220_read_reg(data->spi_device, chan->address);
if (ret < 0)
return -EINVAL;
*val = sign_extend32(ret >> BMA220_DATA_SHIFT, 5);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
ret = bma220_read_reg(data->spi_device, BMA220_REG_RANGE);
if (ret < 0)
return ret;
range_idx = ret & BMA220_RANGE_MASK;
*val = bma220_scale_table[range_idx][0];
*val2 = bma220_scale_table[range_idx][1];
return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
static int bma220_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
int i;
int ret;
int index = -1;
struct bma220_data *data = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_SCALE:
for (i = 0; i < ARRAY_SIZE(bma220_scale_table); i++)
if (val == bma220_scale_table[i][0] &&
val2 == bma220_scale_table[i][1]) {
index = i;
break;
}
if (index < 0)
return -EINVAL;
mutex_lock(&data->lock);
data->tx_buf[0] = BMA220_REG_RANGE;
data->tx_buf[1] = index;
ret = spi_write(data->spi_device, data->tx_buf,
sizeof(data->tx_buf));
if (ret < 0)
dev_err(&data->spi_device->dev,
"failed to set measurement range\n");
mutex_unlock(&data->lock);
return 0;
}
return -EINVAL;
}
static const struct iio_info bma220_info = {
.driver_module = THIS_MODULE,
.read_raw = bma220_read_raw,
.write_raw = bma220_write_raw,
.attrs = &bma220_attribute_group,
};
static int bma220_init(struct spi_device *spi)
{
int ret;
ret = bma220_read_reg(spi, BMA220_REG_ID);
if (ret != BMA220_CHIP_ID)
return -ENODEV;
/* Make sure the chip is powered on */
ret = bma220_read_reg(spi, BMA220_REG_SUSPEND);
if (ret < 0)
return ret;
else if (ret == BMA220_SUSPEND_WAKE)
return bma220_read_reg(spi, BMA220_REG_SUSPEND);
return 0;
}
static int bma220_deinit(struct spi_device *spi)
{
int ret;
/* Make sure the chip is powered off */
ret = bma220_read_reg(spi, BMA220_REG_SUSPEND);
if (ret < 0)
return ret;
else if (ret == BMA220_SUSPEND_SLEEP)
return bma220_read_reg(spi, BMA220_REG_SUSPEND);
return 0;
}
static int bma220_probe(struct spi_device *spi)
{
int ret;
struct iio_dev *indio_dev;
struct bma220_data *data;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data));
if (!indio_dev) {
dev_err(&spi->dev, "iio allocation failed!\n");
return -ENOMEM;
}
data = iio_priv(indio_dev);
data->spi_device = spi;
spi_set_drvdata(spi, indio_dev);
mutex_init(&data->lock);
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &bma220_info;
indio_dev->name = BMA220_DEVICE_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = bma220_channels;
indio_dev->num_channels = ARRAY_SIZE(bma220_channels);
indio_dev->available_scan_masks = bma220_accel_scan_masks;
ret = bma220_init(data->spi_device);
if (ret < 0)
return ret;
ret = iio_triggered_buffer_setup(indio_dev, NULL,
bma220_trigger_handler, NULL);
if (ret < 0) {
dev_err(&spi->dev, "iio triggered buffer setup failed\n");
goto err_suspend;
}
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&spi->dev, "iio_device_register failed\n");
iio_triggered_buffer_cleanup(indio_dev);
goto err_suspend;
}
return 0;
err_suspend:
return bma220_deinit(spi);
}
static int bma220_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
return bma220_deinit(spi);
}
#ifdef CONFIG_PM_SLEEP
static int bma220_suspend(struct device *dev)
{
struct bma220_data *data =
iio_priv(spi_get_drvdata(to_spi_device(dev)));
/* The chip can be suspended/woken up by a simple register read. */
return bma220_read_reg(data->spi_device, BMA220_REG_SUSPEND);
}
static int bma220_resume(struct device *dev)
{
struct bma220_data *data =
iio_priv(spi_get_drvdata(to_spi_device(dev)));
return bma220_read_reg(data->spi_device, BMA220_REG_SUSPEND);
}
static SIMPLE_DEV_PM_OPS(bma220_pm_ops, bma220_suspend, bma220_resume);
#define BMA220_PM_OPS (&bma220_pm_ops)
#else
#define BMA220_PM_OPS NULL
#endif
static const struct spi_device_id bma220_spi_id[] = {
{"bma220", 0},
{}
};
static const struct acpi_device_id bma220_acpi_id[] = {
{"BMA0220", 0},
{}
};
MODULE_DEVICE_TABLE(spi, bma220_spi_id);
static struct spi_driver bma220_driver = {
.driver = {
.name = "bma220_spi",
.pm = BMA220_PM_OPS,
.acpi_match_table = ACPI_PTR(bma220_acpi_id),
},
.probe = bma220_probe,
.remove = bma220_remove,
.id_table = bma220_spi_id,
};
module_spi_driver(bma220_driver);
MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>");
MODULE_DESCRIPTION("BMA220 acceleration sensor driver");
MODULE_LICENSE("GPL v2");
...@@ -901,7 +901,7 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev, ...@@ -901,7 +901,7 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev,
*/ */
if (!irq) { if (!irq) {
data->old_timestamp = data->timestamp; data->old_timestamp = data->timestamp;
data->timestamp = iio_get_time_ns(); data->timestamp = iio_get_time_ns(indio_dev);
} }
/* /*
...@@ -1303,7 +1303,7 @@ static irqreturn_t bmc150_accel_irq_handler(int irq, void *private) ...@@ -1303,7 +1303,7 @@ static irqreturn_t bmc150_accel_irq_handler(int irq, void *private)
int i; int i;
data->old_timestamp = data->timestamp; data->old_timestamp = data->timestamp;
data->timestamp = iio_get_time_ns(); data->timestamp = iio_get_time_ns(indio_dev);
for (i = 0; i < BMC150_ACCEL_TRIGGERS; i++) { for (i = 0; i < BMC150_ACCEL_TRIGGERS; i++) {
if (data->triggers[i].enabled) { if (data->triggers[i].enabled) {
......
...@@ -1129,7 +1129,7 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private) ...@@ -1129,7 +1129,7 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private)
struct iio_dev *indio_dev = private; struct iio_dev *indio_dev = private;
struct kxcjk1013_data *data = iio_priv(indio_dev); struct kxcjk1013_data *data = iio_priv(indio_dev);
data->timestamp = iio_get_time_ns(); data->timestamp = iio_get_time_ns(indio_dev);
if (data->dready_trigger_on) if (data->dready_trigger_on)
iio_trigger_poll(data->dready_trig); iio_trigger_poll(data->dready_trig);
......
...@@ -97,7 +97,8 @@ static irqreturn_t mma7455_trigger_handler(int irq, void *p) ...@@ -97,7 +97,8 @@ static irqreturn_t mma7455_trigger_handler(int irq, void *p)
if (ret) if (ret)
goto done; goto done;
iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); iio_push_to_buffers_with_timestamp(indio_dev, buf,
iio_get_time_ns(indio_dev));
done: done:
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
......
/**
* Freescale MMA7660FC 3-Axis Accelerometer
*
* Copyright (c) 2016, Intel Corporation.
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
* IIO driver for Freescale MMA7660FC; 7-bit I2C address: 0x4c.
*/
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#define MMA7660_DRIVER_NAME "mma7660"
#define MMA7660_REG_XOUT 0x00
#define MMA7660_REG_YOUT 0x01
#define MMA7660_REG_ZOUT 0x02
#define MMA7660_REG_OUT_BIT_ALERT BIT(6)
#define MMA7660_REG_MODE 0x07
#define MMA7660_REG_MODE_BIT_MODE BIT(0)
#define MMA7660_REG_MODE_BIT_TON BIT(2)
#define MMA7660_I2C_READ_RETRIES 5
/*
* The accelerometer has one measurement range:
*
* -1.5g - +1.5g (6-bit, signed)
*
* scale = (1.5 + 1.5) * 9.81 / (2^6 - 1) = 0.467142857
*/
#define MMA7660_SCALE_AVAIL "0.467142857"
const int mma7660_nscale = 467142857;
#define MMA7660_CHANNEL(reg, axis) { \
.type = IIO_ACCEL, \
.address = reg, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
static const struct iio_chan_spec mma7660_channels[] = {
MMA7660_CHANNEL(MMA7660_REG_XOUT, X),
MMA7660_CHANNEL(MMA7660_REG_YOUT, Y),
MMA7660_CHANNEL(MMA7660_REG_ZOUT, Z),
};
enum mma7660_mode {
MMA7660_MODE_STANDBY,
MMA7660_MODE_ACTIVE
};
struct mma7660_data {
struct i2c_client *client;
struct mutex lock;
enum mma7660_mode mode;
};
static IIO_CONST_ATTR(in_accel_scale_available, MMA7660_SCALE_AVAIL);
static struct attribute *mma7660_attributes[] = {
&iio_const_attr_in_accel_scale_available.dev_attr.attr,
NULL,
};
static const struct attribute_group mma7660_attribute_group = {
.attrs = mma7660_attributes
};
static int mma7660_set_mode(struct mma7660_data *data,
enum mma7660_mode mode)
{
int ret;
struct i2c_client *client = data->client;
if (mode == data->mode)
return 0;
ret = i2c_smbus_read_byte_data(client, MMA7660_REG_MODE);
if (ret < 0) {
dev_err(&client->dev, "failed to read sensor mode\n");
return ret;
}
if (mode == MMA7660_MODE_ACTIVE) {
ret &= ~MMA7660_REG_MODE_BIT_TON;
ret |= MMA7660_REG_MODE_BIT_MODE;
} else {
ret &= ~MMA7660_REG_MODE_BIT_TON;
ret &= ~MMA7660_REG_MODE_BIT_MODE;
}
ret = i2c_smbus_write_byte_data(client, MMA7660_REG_MODE, ret);
if (ret < 0) {
dev_err(&client->dev, "failed to change sensor mode\n");
return ret;
}
data->mode = mode;
return ret;
}
static int mma7660_read_accel(struct mma7660_data *data, u8 address)
{
int ret, retries = MMA7660_I2C_READ_RETRIES;
struct i2c_client *client = data->client;
/*
* Read data. If the Alert bit is set, the register was read at
* the same time as the device was attempting to update the content.
* The solution is to read the register again. Do this only
* MMA7660_I2C_READ_RETRIES times to avoid spending too much time
* in the kernel.
*/
do {
ret = i2c_smbus_read_byte_data(client, address);
if (ret < 0) {
dev_err(&client->dev, "register read failed\n");
return ret;
}
} while (retries-- > 0 && ret & MMA7660_REG_OUT_BIT_ALERT);
if (ret & MMA7660_REG_OUT_BIT_ALERT) {
dev_err(&client->dev, "all register read retries failed\n");
return -ETIMEDOUT;
}
return ret;
}
static int mma7660_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct mma7660_data *data = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&data->lock);
ret = mma7660_read_accel(data, chan->address);
mutex_unlock(&data->lock);
if (ret < 0)
return ret;
*val = sign_extend32(ret, 5);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = mma7660_nscale;
return IIO_VAL_INT_PLUS_NANO;
default:
return -EINVAL;
}
return -EINVAL;
}
static const struct iio_info mma7660_info = {
.driver_module = THIS_MODULE,
.read_raw = mma7660_read_raw,
.attrs = &mma7660_attribute_group,
};
static int mma7660_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
struct iio_dev *indio_dev;
struct mma7660_data *data;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev) {
dev_err(&client->dev, "iio allocation failed!\n");
return -ENOMEM;
}
data = iio_priv(indio_dev);
data->client = client;
i2c_set_clientdata(client, indio_dev);
mutex_init(&data->lock);
data->mode = MMA7660_MODE_STANDBY;
indio_dev->dev.parent = &client->dev;
indio_dev->info = &mma7660_info;
indio_dev->name = MMA7660_DRIVER_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = mma7660_channels;
indio_dev->num_channels = ARRAY_SIZE(mma7660_channels);
ret = mma7660_set_mode(data, MMA7660_MODE_ACTIVE);
if (ret < 0)
return ret;
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "device_register failed\n");
mma7660_set_mode(data, MMA7660_MODE_STANDBY);
}
return ret;
}
static int mma7660_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
return mma7660_set_mode(iio_priv(indio_dev), MMA7660_MODE_STANDBY);
}
#ifdef CONFIG_PM_SLEEP
static int mma7660_suspend(struct device *dev)
{
struct mma7660_data *data;
data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
return mma7660_set_mode(data, MMA7660_MODE_STANDBY);
}
static int mma7660_resume(struct device *dev)
{
struct mma7660_data *data;
data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
return mma7660_set_mode(data, MMA7660_MODE_ACTIVE);
}
static SIMPLE_DEV_PM_OPS(mma7660_pm_ops, mma7660_suspend, mma7660_resume);
#define MMA7660_PM_OPS (&mma7660_pm_ops)
#else
#define MMA7660_PM_OPS NULL
#endif
static const struct i2c_device_id mma7660_i2c_id[] = {
{"mma7660", 0},
{}
};
static const struct acpi_device_id mma7660_acpi_id[] = {
{"MMA7660", 0},
{}
};
MODULE_DEVICE_TABLE(acpi, mma7660_acpi_id);
static struct i2c_driver mma7660_driver = {
.driver = {
.name = "mma7660",
.pm = MMA7660_PM_OPS,
.acpi_match_table = ACPI_PTR(mma7660_acpi_id),
},
.probe = mma7660_probe,
.remove = mma7660_remove,
.id_table = mma7660_i2c_id,
};
module_i2c_driver(mma7660_driver);
MODULE_AUTHOR("Constantin Musca <constantin.musca@intel.com>");
MODULE_DESCRIPTION("Freescale MMA7660FC 3-Axis Accelerometer driver");
MODULE_LICENSE("GPL v2");
/* /*
* mma8452.c - Support for following Freescale 3-axis accelerometers: * mma8452.c - Support for following Freescale / NXP 3-axis accelerometers:
* *
* MMA8451Q (14 bit) * device name digital output 7-bit I2C slave address (pin selectable)
* MMA8452Q (12 bit) * ---------------------------------------------------------------------
* MMA8453Q (10 bit) * MMA8451Q 14 bit 0x1c / 0x1d
* MMA8652FC (12 bit) * MMA8452Q 12 bit 0x1c / 0x1d
* MMA8653FC (10 bit) * MMA8453Q 10 bit 0x1c / 0x1d
* FXLS8471Q (14 bit) * MMA8652FC 12 bit 0x1d
* MMA8653FC 10 bit 0x1d
* FXLS8471Q 14 bit 0x1e / 0x1d / 0x1c / 0x1f
* *
* Copyright 2015 Martin Kepplinger <martin.kepplinger@theobroma-systems.com> * Copyright 2015 Martin Kepplinger <martink@posteo.de>
* Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net> * Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net>
* *
* This file is subject to the terms and conditions of version 2 of * 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 * the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details. * directory of this archive for more details.
* *
* 7-bit I2C slave address 0x1c/0x1d (pin selectable)
*
* TODO: orientation events * TODO: orientation events
*/ */
...@@ -76,6 +76,8 @@ ...@@ -76,6 +76,8 @@
#define MMA8452_CTRL_DR_DEFAULT 0x4 /* 50 Hz sample frequency */ #define MMA8452_CTRL_DR_DEFAULT 0x4 /* 50 Hz sample frequency */
#define MMA8452_CTRL_REG2 0x2b #define MMA8452_CTRL_REG2 0x2b
#define MMA8452_CTRL_REG2_RST BIT(6) #define MMA8452_CTRL_REG2_RST BIT(6)
#define MMA8452_CTRL_REG2_MODS_SHIFT 3
#define MMA8452_CTRL_REG2_MODS_MASK 0x1b
#define MMA8452_CTRL_REG4 0x2d #define MMA8452_CTRL_REG4 0x2d
#define MMA8452_CTRL_REG5 0x2e #define MMA8452_CTRL_REG5 0x2e
#define MMA8452_OFF_X 0x2f #define MMA8452_OFF_X 0x2f
...@@ -106,7 +108,7 @@ struct mma8452_data { ...@@ -106,7 +108,7 @@ struct mma8452_data {
}; };
/** /**
* struct mma_chip_info - chip specific data for Freescale's accelerometers * struct mma_chip_info - chip specific data
* @chip_id: WHO_AM_I register's value * @chip_id: WHO_AM_I register's value
* @channels: struct iio_chan_spec matching the device's * @channels: struct iio_chan_spec matching the device's
* capabilities * capabilities
...@@ -257,20 +259,17 @@ static const int mma8452_samp_freq[8][2] = { ...@@ -257,20 +259,17 @@ static const int mma8452_samp_freq[8][2] = {
{6, 250000}, {1, 560000} {6, 250000}, {1, 560000}
}; };
/* Datasheet table 35 (step time vs sample frequency) */ /* Datasheet table: step time "Relationship with the ODR" (sample frequency) */
static const int mma8452_transient_time_step_us[8] = { static const int mma8452_transient_time_step_us[4][8] = {
1250, { 1250, 2500, 5000, 10000, 20000, 20000, 20000, 20000 }, /* normal */
2500, { 1250, 2500, 5000, 10000, 20000, 80000, 80000, 80000 }, /* l p l n */
5000, { 1250, 2500, 2500, 2500, 2500, 2500, 2500, 2500 }, /* high res*/
10000, { 1250, 2500, 5000, 10000, 20000, 80000, 160000, 160000 } /* l p */
20000,
20000,
20000,
20000
}; };
/* Datasheet table 18 (normal mode) */ /* Datasheet table "High-Pass Filter Cutoff Options" */
static const int mma8452_hp_filter_cutoff[8][4][2] = { static const int mma8452_hp_filter_cutoff[4][8][4][2] = {
{ /* normal */
{ {16, 0}, {8, 0}, {4, 0}, {2, 0} }, /* 800 Hz sample */ { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, /* 800 Hz sample */
{ {16, 0}, {8, 0}, {4, 0}, {2, 0} }, /* 400 Hz sample */ { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, /* 400 Hz sample */
{ {8, 0}, {4, 0}, {2, 0}, {1, 0} }, /* 200 Hz sample */ { {8, 0}, {4, 0}, {2, 0}, {1, 0} }, /* 200 Hz sample */
...@@ -279,8 +278,61 @@ static const int mma8452_hp_filter_cutoff[8][4][2] = { ...@@ -279,8 +278,61 @@ static const int mma8452_hp_filter_cutoff[8][4][2] = {
{ {2, 0}, {1, 0}, {0, 500000}, {0, 250000} }, /* 12.5 Hz sample */ { {2, 0}, {1, 0}, {0, 500000}, {0, 250000} }, /* 12.5 Hz sample */
{ {2, 0}, {1, 0}, {0, 500000}, {0, 250000} }, /* 6.25 Hz sample */ { {2, 0}, {1, 0}, {0, 500000}, {0, 250000} }, /* 6.25 Hz sample */
{ {2, 0}, {1, 0}, {0, 500000}, {0, 250000} } /* 1.56 Hz sample */ { {2, 0}, {1, 0}, {0, 500000}, {0, 250000} } /* 1.56 Hz sample */
},
{ /* low noise low power */
{ {16, 0}, {8, 0}, {4, 0}, {2, 0} },
{ {16, 0}, {8, 0}, {4, 0}, {2, 0} },
{ {8, 0}, {4, 0}, {2, 0}, {1, 0} },
{ {4, 0}, {2, 0}, {1, 0}, {0, 500000} },
{ {2, 0}, {1, 0}, {0, 500000}, {0, 250000} },
{ {0, 500000}, {0, 250000}, {0, 125000}, {0, 063000} },
{ {0, 500000}, {0, 250000}, {0, 125000}, {0, 063000} },
{ {0, 500000}, {0, 250000}, {0, 125000}, {0, 063000} }
},
{ /* high resolution */
{ {16, 0}, {8, 0}, {4, 0}, {2, 0} },
{ {16, 0}, {8, 0}, {4, 0}, {2, 0} },
{ {16, 0}, {8, 0}, {4, 0}, {2, 0} },
{ {16, 0}, {8, 0}, {4, 0}, {2, 0} },
{ {16, 0}, {8, 0}, {4, 0}, {2, 0} },
{ {16, 0}, {8, 0}, {4, 0}, {2, 0} },
{ {16, 0}, {8, 0}, {4, 0}, {2, 0} },
{ {16, 0}, {8, 0}, {4, 0}, {2, 0} }
},
{ /* low power */
{ {16, 0}, {8, 0}, {4, 0}, {2, 0} },
{ {8, 0}, {4, 0}, {2, 0}, {1, 0} },
{ {4, 0}, {2, 0}, {1, 0}, {0, 500000} },
{ {2, 0}, {1, 0}, {0, 500000}, {0, 250000} },
{ {1, 0}, {0, 500000}, {0, 250000}, {0, 125000} },
{ {0, 250000}, {0, 125000}, {0, 063000}, {0, 031000} },
{ {0, 250000}, {0, 125000}, {0, 063000}, {0, 031000} },
{ {0, 250000}, {0, 125000}, {0, 063000}, {0, 031000} }
}
}; };
/* Datasheet table "MODS Oversampling modes averaging values at each ODR" */
static const u16 mma8452_os_ratio[4][8] = {
/* 800 Hz, 400 Hz, ... , 1.56 Hz */
{ 2, 4, 4, 4, 4, 16, 32, 128 }, /* normal */
{ 2, 4, 4, 4, 4, 4, 8, 32 }, /* low power low noise */
{ 2, 4, 8, 16, 32, 128, 256, 1024 }, /* high resolution */
{ 2, 2, 2, 2, 2, 2, 4, 16 } /* low power */
};
static int mma8452_get_power_mode(struct mma8452_data *data)
{
int reg;
reg = i2c_smbus_read_byte_data(data->client,
MMA8452_CTRL_REG2);
if (reg < 0)
return reg;
return ((reg & MMA8452_CTRL_REG2_MODS_MASK) >>
MMA8452_CTRL_REG2_MODS_SHIFT);
}
static ssize_t mma8452_show_samp_freq_avail(struct device *dev, static ssize_t mma8452_show_samp_freq_avail(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
...@@ -303,13 +355,42 @@ static ssize_t mma8452_show_scale_avail(struct device *dev, ...@@ -303,13 +355,42 @@ static ssize_t mma8452_show_scale_avail(struct device *dev,
static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev, static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct mma8452_data *data = iio_priv(indio_dev);
int i, j;
i = mma8452_get_odr_index(data);
j = mma8452_get_power_mode(data);
if (j < 0)
return j;
return mma8452_show_int_plus_micros(buf, mma8452_hp_filter_cutoff[j][i],
ARRAY_SIZE(mma8452_hp_filter_cutoff[0][0]));
}
static ssize_t mma8452_show_os_ratio_avail(struct device *dev,
struct device_attribute *attr,
char *buf)
{ {
struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct mma8452_data *data = iio_priv(indio_dev); struct mma8452_data *data = iio_priv(indio_dev);
int i = mma8452_get_odr_index(data); int i = mma8452_get_odr_index(data);
int j;
u16 val = 0;
size_t len = 0;
return mma8452_show_int_plus_micros(buf, mma8452_hp_filter_cutoff[i], for (j = 0; j < ARRAY_SIZE(mma8452_os_ratio); j++) {
ARRAY_SIZE(mma8452_hp_filter_cutoff[0])); if (val == mma8452_os_ratio[j][i])
continue;
val = mma8452_os_ratio[j][i];
len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", val);
}
buf[len - 1] = '\n';
return len;
} }
static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mma8452_show_samp_freq_avail); static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mma8452_show_samp_freq_avail);
...@@ -317,6 +398,8 @@ static IIO_DEVICE_ATTR(in_accel_scale_available, S_IRUGO, ...@@ -317,6 +398,8 @@ static IIO_DEVICE_ATTR(in_accel_scale_available, S_IRUGO,
mma8452_show_scale_avail, NULL, 0); mma8452_show_scale_avail, NULL, 0);
static IIO_DEVICE_ATTR(in_accel_filter_high_pass_3db_frequency_available, static IIO_DEVICE_ATTR(in_accel_filter_high_pass_3db_frequency_available,
S_IRUGO, mma8452_show_hp_cutoff_avail, NULL, 0); S_IRUGO, mma8452_show_hp_cutoff_avail, NULL, 0);
static IIO_DEVICE_ATTR(in_accel_oversampling_ratio_available, S_IRUGO,
mma8452_show_os_ratio_avail, NULL, 0);
static int mma8452_get_samp_freq_index(struct mma8452_data *data, static int mma8452_get_samp_freq_index(struct mma8452_data *data,
int val, int val2) int val, int val2)
...@@ -335,24 +418,33 @@ static int mma8452_get_scale_index(struct mma8452_data *data, int val, int val2) ...@@ -335,24 +418,33 @@ static int mma8452_get_scale_index(struct mma8452_data *data, int val, int val2)
static int mma8452_get_hp_filter_index(struct mma8452_data *data, static int mma8452_get_hp_filter_index(struct mma8452_data *data,
int val, int val2) int val, int val2)
{ {
int i = mma8452_get_odr_index(data); int i, j;
i = mma8452_get_odr_index(data);
j = mma8452_get_power_mode(data);
if (j < 0)
return j;
return mma8452_get_int_plus_micros_index(mma8452_hp_filter_cutoff[i], return mma8452_get_int_plus_micros_index(mma8452_hp_filter_cutoff[j][i],
ARRAY_SIZE(mma8452_hp_filter_cutoff[0]), val, val2); ARRAY_SIZE(mma8452_hp_filter_cutoff[0][0]), val, val2);
} }
static int mma8452_read_hp_filter(struct mma8452_data *data, int *hz, int *uHz) static int mma8452_read_hp_filter(struct mma8452_data *data, int *hz, int *uHz)
{ {
int i, ret; int j, i, ret;
ret = i2c_smbus_read_byte_data(data->client, MMA8452_HP_FILTER_CUTOFF); ret = i2c_smbus_read_byte_data(data->client, MMA8452_HP_FILTER_CUTOFF);
if (ret < 0) if (ret < 0)
return ret; return ret;
i = mma8452_get_odr_index(data); i = mma8452_get_odr_index(data);
j = mma8452_get_power_mode(data);
if (j < 0)
return j;
ret &= MMA8452_HP_FILTER_CUTOFF_SEL_MASK; ret &= MMA8452_HP_FILTER_CUTOFF_SEL_MASK;
*hz = mma8452_hp_filter_cutoff[i][ret][0]; *hz = mma8452_hp_filter_cutoff[j][i][ret][0];
*uHz = mma8452_hp_filter_cutoff[i][ret][1]; *uHz = mma8452_hp_filter_cutoff[j][i][ret][1];
return 0; return 0;
} }
...@@ -414,6 +506,15 @@ static int mma8452_read_raw(struct iio_dev *indio_dev, ...@@ -414,6 +506,15 @@ static int mma8452_read_raw(struct iio_dev *indio_dev,
} }
return IIO_VAL_INT_PLUS_MICRO; return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
ret = mma8452_get_power_mode(data);
if (ret < 0)
return ret;
i = mma8452_get_odr_index(data);
*val = mma8452_os_ratio[ret][i];
return IIO_VAL_INT;
} }
return -EINVAL; return -EINVAL;
...@@ -480,6 +581,21 @@ static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val) ...@@ -480,6 +581,21 @@ static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val)
return ret; return ret;
} }
static int mma8452_set_power_mode(struct mma8452_data *data, u8 mode)
{
int reg;
reg = i2c_smbus_read_byte_data(data->client,
MMA8452_CTRL_REG2);
if (reg < 0)
return reg;
reg &= ~MMA8452_CTRL_REG2_MODS_MASK;
reg |= mode << MMA8452_CTRL_REG2_MODS_SHIFT;
return mma8452_change_config(data, MMA8452_CTRL_REG2, reg);
}
/* returns >0 if in freefall mode, 0 if not or <0 if an error occurred */ /* returns >0 if in freefall mode, 0 if not or <0 if an error occurred */
static int mma8452_freefall_mode_enabled(struct mma8452_data *data) static int mma8452_freefall_mode_enabled(struct mma8452_data *data)
{ {
...@@ -518,11 +634,7 @@ static int mma8452_set_freefall_mode(struct mma8452_data *data, bool state) ...@@ -518,11 +634,7 @@ static int mma8452_set_freefall_mode(struct mma8452_data *data, bool state)
val |= MMA8452_FF_MT_CFG_OAE; val |= MMA8452_FF_MT_CFG_OAE;
} }
val = mma8452_change_config(data, chip->ev_cfg, val); return 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, static int mma8452_set_hp_filter_frequency(struct mma8452_data *data,
...@@ -597,6 +709,14 @@ static int mma8452_write_raw(struct iio_dev *indio_dev, ...@@ -597,6 +709,14 @@ static int mma8452_write_raw(struct iio_dev *indio_dev,
return mma8452_change_config(data, MMA8452_DATA_CFG, return mma8452_change_config(data, MMA8452_DATA_CFG,
data->data_cfg); data->data_cfg);
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
ret = mma8452_get_odr_index(data);
for (i = 0; i < ARRAY_SIZE(mma8452_os_ratio); i++) {
if (mma8452_os_ratio[i][ret] == val)
return mma8452_set_power_mode(data, i);
}
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -610,7 +730,7 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev, ...@@ -610,7 +730,7 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev,
int *val, int *val2) int *val, int *val2)
{ {
struct mma8452_data *data = iio_priv(indio_dev); struct mma8452_data *data = iio_priv(indio_dev);
int ret, us; int ret, us, power_mode;
switch (info) { switch (info) {
case IIO_EV_INFO_VALUE: case IIO_EV_INFO_VALUE:
...@@ -629,7 +749,11 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev, ...@@ -629,7 +749,11 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev,
if (ret < 0) if (ret < 0)
return ret; return ret;
us = ret * mma8452_transient_time_step_us[ power_mode = mma8452_get_power_mode(data);
if (power_mode < 0)
return power_mode;
us = ret * mma8452_transient_time_step_us[power_mode][
mma8452_get_odr_index(data)]; mma8452_get_odr_index(data)];
*val = us / USEC_PER_SEC; *val = us / USEC_PER_SEC;
*val2 = us % USEC_PER_SEC; *val2 = us % USEC_PER_SEC;
...@@ -677,8 +801,12 @@ static int mma8452_write_thresh(struct iio_dev *indio_dev, ...@@ -677,8 +801,12 @@ static int mma8452_write_thresh(struct iio_dev *indio_dev,
val); val);
case IIO_EV_INFO_PERIOD: case IIO_EV_INFO_PERIOD:
ret = mma8452_get_power_mode(data);
if (ret < 0)
return ret;
steps = (val * USEC_PER_SEC + val2) / steps = (val * USEC_PER_SEC + val2) /
mma8452_transient_time_step_us[ mma8452_transient_time_step_us[ret][
mma8452_get_odr_index(data)]; mma8452_get_odr_index(data)];
if (steps < 0 || steps > 0xff) if (steps < 0 || steps > 0xff)
...@@ -785,7 +913,7 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev, ...@@ -785,7 +913,7 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev,
static void mma8452_transient_interrupt(struct iio_dev *indio_dev) static void mma8452_transient_interrupt(struct iio_dev *indio_dev)
{ {
struct mma8452_data *data = iio_priv(indio_dev); struct mma8452_data *data = iio_priv(indio_dev);
s64 ts = iio_get_time_ns(); s64 ts = iio_get_time_ns(indio_dev);
int src; int src;
src = i2c_smbus_read_byte_data(data->client, data->chip_info->ev_src); src = i2c_smbus_read_byte_data(data->client, data->chip_info->ev_src);
...@@ -865,7 +993,7 @@ static irqreturn_t mma8452_trigger_handler(int irq, void *p) ...@@ -865,7 +993,7 @@ static irqreturn_t mma8452_trigger_handler(int irq, void *p)
goto done; goto done;
iio_push_to_buffers_with_timestamp(indio_dev, buffer, iio_push_to_buffers_with_timestamp(indio_dev, buffer,
iio_get_time_ns()); iio_get_time_ns(indio_dev));
done: done:
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
...@@ -978,7 +1106,8 @@ static struct attribute_group mma8452_event_attribute_group = { ...@@ -978,7 +1106,8 @@ static struct attribute_group mma8452_event_attribute_group = {
BIT(IIO_CHAN_INFO_CALIBBIAS), \ BIT(IIO_CHAN_INFO_CALIBBIAS), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \ BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY) | \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
.scan_index = idx, \ .scan_index = idx, \
.scan_type = { \ .scan_type = { \
.sign = 's', \ .sign = 's', \
...@@ -998,7 +1127,8 @@ static struct attribute_group mma8452_event_attribute_group = { ...@@ -998,7 +1127,8 @@ static struct attribute_group mma8452_event_attribute_group = {
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_CALIBBIAS), \ BIT(IIO_CHAN_INFO_CALIBBIAS), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
BIT(IIO_CHAN_INFO_SCALE), \ BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
.scan_index = idx, \ .scan_index = idx, \
.scan_type = { \ .scan_type = { \
.sign = 's', \ .sign = 's', \
...@@ -1171,6 +1301,7 @@ static struct attribute *mma8452_attributes[] = { ...@@ -1171,6 +1301,7 @@ static struct attribute *mma8452_attributes[] = {
&iio_dev_attr_sampling_frequency_available.dev_attr.attr, &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_in_accel_scale_available.dev_attr.attr, &iio_dev_attr_in_accel_scale_available.dev_attr.attr,
&iio_dev_attr_in_accel_filter_high_pass_3db_frequency_available.dev_attr.attr, &iio_dev_attr_in_accel_filter_high_pass_3db_frequency_available.dev_attr.attr,
&iio_dev_attr_in_accel_oversampling_ratio_available.dev_attr.attr,
NULL NULL
}; };
...@@ -1444,8 +1575,8 @@ static int mma8452_probe(struct i2c_client *client, ...@@ -1444,8 +1575,8 @@ static int mma8452_probe(struct i2c_client *client,
goto buffer_cleanup; goto buffer_cleanup;
ret = mma8452_set_freefall_mode(data, false); ret = mma8452_set_freefall_mode(data, false);
if (ret) if (ret < 0)
return ret; goto buffer_cleanup;
return 0; return 0;
...@@ -1558,5 +1689,5 @@ static struct i2c_driver mma8452_driver = { ...@@ -1558,5 +1689,5 @@ static struct i2c_driver mma8452_driver = {
module_i2c_driver(mma8452_driver); module_i2c_driver(mma8452_driver);
MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
MODULE_DESCRIPTION("Freescale MMA8452 accelerometer driver"); MODULE_DESCRIPTION("Freescale / NXP MMA8452 accelerometer driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -391,7 +391,7 @@ static irqreturn_t mma9551_event_handler(int irq, void *private) ...@@ -391,7 +391,7 @@ static irqreturn_t mma9551_event_handler(int irq, void *private)
iio_push_event(indio_dev, iio_push_event(indio_dev,
IIO_MOD_EVENT_CODE(IIO_INCLI, 0, (mma_axis + 1), IIO_MOD_EVENT_CODE(IIO_INCLI, 0, (mma_axis + 1),
IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING), IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING),
iio_get_time_ns()); iio_get_time_ns(indio_dev));
out: out:
mutex_unlock(&data->mutex); mutex_unlock(&data->mutex);
......
...@@ -1001,7 +1001,7 @@ static irqreturn_t mma9553_irq_handler(int irq, void *private) ...@@ -1001,7 +1001,7 @@ static irqreturn_t mma9553_irq_handler(int irq, void *private)
struct iio_dev *indio_dev = private; struct iio_dev *indio_dev = private;
struct mma9553_data *data = iio_priv(indio_dev); struct mma9553_data *data = iio_priv(indio_dev);
data->timestamp = iio_get_time_ns(); data->timestamp = iio_get_time_ns(indio_dev);
/* /*
* Since we only configure the interrupt pin when an * Since we only configure the interrupt pin when an
* event is enabled, we are sure we have at least * event is enabled, we are sure we have at least
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#define LSM330_ACCEL_DEV_NAME "lsm330_accel" #define LSM330_ACCEL_DEV_NAME "lsm330_accel"
#define LSM303AGR_ACCEL_DEV_NAME "lsm303agr_accel" #define LSM303AGR_ACCEL_DEV_NAME "lsm303agr_accel"
#define LIS2DH12_ACCEL_DEV_NAME "lis2dh12_accel" #define LIS2DH12_ACCEL_DEV_NAME "lis2dh12_accel"
#define LIS3L02DQ_ACCEL_DEV_NAME "lis3l02dq"
/** /**
* struct st_sensors_platform_data - default accel platform data * struct st_sensors_platform_data - default accel platform data
......
...@@ -215,6 +215,22 @@ ...@@ -215,6 +215,22 @@
#define ST_ACCEL_6_IHL_IRQ_MASK 0x80 #define ST_ACCEL_6_IHL_IRQ_MASK 0x80
#define ST_ACCEL_6_MULTIREAD_BIT true #define ST_ACCEL_6_MULTIREAD_BIT true
/* CUSTOM VALUES FOR SENSOR 7 */
#define ST_ACCEL_7_ODR_ADDR 0x20
#define ST_ACCEL_7_ODR_MASK 0x30
#define ST_ACCEL_7_ODR_AVL_280HZ_VAL 0x00
#define ST_ACCEL_7_ODR_AVL_560HZ_VAL 0x01
#define ST_ACCEL_7_ODR_AVL_1120HZ_VAL 0x02
#define ST_ACCEL_7_ODR_AVL_4480HZ_VAL 0x03
#define ST_ACCEL_7_PW_ADDR 0x20
#define ST_ACCEL_7_PW_MASK 0xc0
#define ST_ACCEL_7_FS_AVL_2_GAIN IIO_G_TO_M_S_2(488)
#define ST_ACCEL_7_BDU_ADDR 0x21
#define ST_ACCEL_7_BDU_MASK 0x40
#define ST_ACCEL_7_DRDY_IRQ_ADDR 0x21
#define ST_ACCEL_7_DRDY_IRQ_INT1_MASK 0x04
#define ST_ACCEL_7_MULTIREAD_BIT false
static const struct iio_chan_spec st_accel_8bit_channels[] = { static const struct iio_chan_spec st_accel_8bit_channels[] = {
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
...@@ -662,6 +678,54 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { ...@@ -662,6 +678,54 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.multi_read_bit = ST_ACCEL_6_MULTIREAD_BIT, .multi_read_bit = ST_ACCEL_6_MULTIREAD_BIT,
.bootime = 2, .bootime = 2,
}, },
{
/* No WAI register present */
.sensors_supported = {
[0] = LIS3L02DQ_ACCEL_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_accel_12bit_channels,
.odr = {
.addr = ST_ACCEL_7_ODR_ADDR,
.mask = ST_ACCEL_7_ODR_MASK,
.odr_avl = {
{ 280, ST_ACCEL_7_ODR_AVL_280HZ_VAL, },
{ 560, ST_ACCEL_7_ODR_AVL_560HZ_VAL, },
{ 1120, ST_ACCEL_7_ODR_AVL_1120HZ_VAL, },
{ 4480, ST_ACCEL_7_ODR_AVL_4480HZ_VAL, },
},
},
.pw = {
.addr = ST_ACCEL_7_PW_ADDR,
.mask = ST_ACCEL_7_PW_MASK,
.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
},
.enable_axis = {
.addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
},
.fs = {
.fs_avl = {
[0] = {
.num = ST_ACCEL_FS_AVL_2G,
.gain = ST_ACCEL_7_FS_AVL_2_GAIN,
},
},
},
/*
* The part has a BDU bit but if set the data is never
* updated so don't set it.
*/
.bdu = {
},
.drdy_irq = {
.addr = ST_ACCEL_7_DRDY_IRQ_ADDR,
.mask_int1 = ST_ACCEL_7_DRDY_IRQ_INT1_MASK,
.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
},
.multi_read_bit = ST_ACCEL_7_MULTIREAD_BIT,
.bootime = 2,
},
}; };
static int st_accel_read_raw(struct iio_dev *indio_dev, static int st_accel_read_raw(struct iio_dev *indio_dev,
...@@ -758,13 +822,15 @@ int st_accel_common_probe(struct iio_dev *indio_dev) ...@@ -758,13 +822,15 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
indio_dev->info = &accel_info; indio_dev->info = &accel_info;
mutex_init(&adata->tb.buf_lock); mutex_init(&adata->tb.buf_lock);
st_sensors_power_enable(indio_dev); err = st_sensors_power_enable(indio_dev);
if (err)
return err;
err = st_sensors_check_device_support(indio_dev, err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_accel_sensors_settings), ARRAY_SIZE(st_accel_sensors_settings),
st_accel_sensors_settings); st_accel_sensors_settings);
if (err < 0) if (err < 0)
return err; goto st_accel_power_off;
adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS; adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS;
adata->multiread_bit = adata->sensor_settings->multi_read_bit; adata->multiread_bit = adata->sensor_settings->multi_read_bit;
...@@ -781,11 +847,11 @@ int st_accel_common_probe(struct iio_dev *indio_dev) ...@@ -781,11 +847,11 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
err = st_sensors_init_sensor(indio_dev, adata->dev->platform_data); err = st_sensors_init_sensor(indio_dev, adata->dev->platform_data);
if (err < 0) if (err < 0)
return err; goto st_accel_power_off;
err = st_accel_allocate_ring(indio_dev); err = st_accel_allocate_ring(indio_dev);
if (err < 0) if (err < 0)
return err; goto st_accel_power_off;
if (irq > 0) { if (irq > 0) {
err = st_sensors_allocate_trigger(indio_dev, err = st_sensors_allocate_trigger(indio_dev,
...@@ -808,6 +874,8 @@ int st_accel_common_probe(struct iio_dev *indio_dev) ...@@ -808,6 +874,8 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
st_sensors_deallocate_trigger(indio_dev); st_sensors_deallocate_trigger(indio_dev);
st_accel_probe_trigger_error: st_accel_probe_trigger_error:
st_accel_deallocate_ring(indio_dev); st_accel_deallocate_ring(indio_dev);
st_accel_power_off:
st_sensors_power_disable(indio_dev);
return err; return err;
} }
......
...@@ -80,6 +80,10 @@ static const struct of_device_id st_accel_of_match[] = { ...@@ -80,6 +80,10 @@ static const struct of_device_id st_accel_of_match[] = {
.compatible = "st,h3lis331dl-accel", .compatible = "st,h3lis331dl-accel",
.data = H3LIS331DL_DRIVER_NAME, .data = H3LIS331DL_DRIVER_NAME,
}, },
{
.compatible = "st,lis3l02dq",
.data = LIS3L02DQ_ACCEL_DEV_NAME,
},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, st_accel_of_match); MODULE_DEVICE_TABLE(of, st_accel_of_match);
...@@ -130,6 +134,7 @@ static const struct i2c_device_id st_accel_id_table[] = { ...@@ -130,6 +134,7 @@ static const struct i2c_device_id st_accel_id_table[] = {
{ LSM330_ACCEL_DEV_NAME }, { LSM330_ACCEL_DEV_NAME },
{ LSM303AGR_ACCEL_DEV_NAME }, { LSM303AGR_ACCEL_DEV_NAME },
{ LIS2DH12_ACCEL_DEV_NAME }, { LIS2DH12_ACCEL_DEV_NAME },
{ LIS3L02DQ_ACCEL_DEV_NAME },
{}, {},
}; };
MODULE_DEVICE_TABLE(i2c, st_accel_id_table); MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
......
...@@ -59,6 +59,7 @@ static const struct spi_device_id st_accel_id_table[] = { ...@@ -59,6 +59,7 @@ static const struct spi_device_id st_accel_id_table[] = {
{ LSM330_ACCEL_DEV_NAME }, { LSM330_ACCEL_DEV_NAME },
{ LSM303AGR_ACCEL_DEV_NAME }, { LSM303AGR_ACCEL_DEV_NAME },
{ LIS2DH12_ACCEL_DEV_NAME }, { LIS2DH12_ACCEL_DEV_NAME },
{ LIS3L02DQ_ACCEL_DEV_NAME },
{}, {},
}; };
MODULE_DEVICE_TABLE(spi, st_accel_id_table); MODULE_DEVICE_TABLE(spi, st_accel_id_table);
......
...@@ -153,6 +153,18 @@ config AXP288_ADC ...@@ -153,6 +153,18 @@ config AXP288_ADC
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called axp288_adc. called axp288_adc.
config BCM_IPROC_ADC
tristate "Broadcom IPROC ADC driver"
depends on ARCH_BCM_IPROC || COMPILE_TEST
depends on MFD_SYSCON
default ARCH_BCM_CYGNUS
help
Say Y here if you want to add support for the Broadcom static
ADC driver.
Broadcom iProc ADC driver. Broadcom iProc ADC controller has 8
channels. The driver allows the user to read voltage values.
config BERLIN2_ADC config BERLIN2_ADC
tristate "Marvell Berlin2 ADC driver" tristate "Marvell Berlin2 ADC driver"
depends on ARCH_BERLIN depends on ARCH_BERLIN
......
...@@ -16,6 +16,7 @@ obj-$(CONFIG_AD799X) += ad799x.o ...@@ -16,6 +16,7 @@ obj-$(CONFIG_AD799X) += ad799x.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o
obj-$(CONFIG_AXP288_ADC) += axp288_adc.o obj-$(CONFIG_AXP288_ADC) += axp288_adc.o
obj-$(CONFIG_BCM_IPROC_ADC) += bcm_iproc_adc.o
obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o
obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o
obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
......
...@@ -154,12 +154,11 @@ static int ad7266_read_raw(struct iio_dev *indio_dev, ...@@ -154,12 +154,11 @@ static int ad7266_read_raw(struct iio_dev *indio_dev,
switch (m) { switch (m) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
if (iio_buffer_enabled(indio_dev)) ret = iio_device_claim_direct_mode(indio_dev);
return -EBUSY;
ret = ad7266_read_single(st, val, chan->address);
if (ret) if (ret)
return ret; return ret;
ret = ad7266_read_single(st, val, chan->address);
iio_device_release_direct_mode(indio_dev);
*val = (*val >> 2) & 0xfff; *val = (*val >> 2) & 0xfff;
if (chan->scan_type.sign == 's') if (chan->scan_type.sign == 's')
...@@ -441,6 +440,7 @@ static int ad7266_probe(struct spi_device *spi) ...@@ -441,6 +440,7 @@ static int ad7266_probe(struct spi_device *spi)
st->spi = spi; st->spi = spi;
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->dev.of_node = spi->dev.of_node;
indio_dev->name = spi_get_device_id(spi)->name; indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &ad7266_info; indio_dev->info = &ad7266_info;
......
...@@ -115,7 +115,7 @@ static irqreturn_t ad7291_event_handler(int irq, void *private) ...@@ -115,7 +115,7 @@ static irqreturn_t ad7291_event_handler(int irq, void *private)
u16 t_status, v_status; u16 t_status, v_status;
u16 command; u16 command;
int i; int i;
s64 timestamp = iio_get_time_ns(); s64 timestamp = iio_get_time_ns(indio_dev);
if (ad7291_i2c_read(chip, AD7291_T_ALERT_STATUS, &t_status)) if (ad7291_i2c_read(chip, AD7291_T_ALERT_STATUS, &t_status))
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -505,6 +505,7 @@ static int ad7291_probe(struct i2c_client *client, ...@@ -505,6 +505,7 @@ static int ad7291_probe(struct i2c_client *client,
indio_dev->num_channels = ARRAY_SIZE(ad7291_channels); indio_dev->num_channels = ARRAY_SIZE(ad7291_channels);
indio_dev->dev.parent = &client->dev; indio_dev->dev.parent = &client->dev;
indio_dev->dev.of_node = client->dev.of_node;
indio_dev->info = &ad7291_info; indio_dev->info = &ad7291_info;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
......
...@@ -163,7 +163,7 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p) ...@@ -163,7 +163,7 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p)
goto done; goto done;
iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf, iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
iio_get_time_ns()); iio_get_time_ns(indio_dev));
done: done:
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
...@@ -315,6 +315,7 @@ static int ad7298_probe(struct spi_device *spi) ...@@ -315,6 +315,7 @@ static int ad7298_probe(struct spi_device *spi)
indio_dev->name = spi_get_device_id(spi)->name; indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->dev.of_node = spi->dev.of_node;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = ad7298_channels; indio_dev->channels = ad7298_channels;
indio_dev->num_channels = ARRAY_SIZE(ad7298_channels); indio_dev->num_channels = ARRAY_SIZE(ad7298_channels);
......
...@@ -70,7 +70,7 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p) ...@@ -70,7 +70,7 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p)
goto done; goto done;
iio_push_to_buffers_with_timestamp(indio_dev, st->data, iio_push_to_buffers_with_timestamp(indio_dev, st->data,
iio_get_time_ns()); iio_get_time_ns(indio_dev));
done: done:
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
...@@ -106,12 +106,11 @@ static int ad7476_read_raw(struct iio_dev *indio_dev, ...@@ -106,12 +106,11 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
switch (m) { switch (m) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (iio_buffer_enabled(indio_dev)) if (ret)
ret = -EBUSY; return ret;
else ret = ad7476_scan_direct(st);
ret = ad7476_scan_direct(st); iio_device_release_direct_mode(indio_dev);
mutex_unlock(&indio_dev->mlock);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -228,6 +227,7 @@ static int ad7476_probe(struct spi_device *spi) ...@@ -228,6 +227,7 @@ static int ad7476_probe(struct spi_device *spi)
/* Establish that the iio_dev is a child of the spi device */ /* Establish that the iio_dev is a child of the spi device */
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->dev.of_node = spi->dev.of_node;
indio_dev->name = spi_get_device_id(spi)->name; indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = st->chip_info->channel; indio_dev->channels = st->chip_info->channel;
......
...@@ -272,30 +272,22 @@ static ssize_t ad7791_write_frequency(struct device *dev, ...@@ -272,30 +272,22 @@ static ssize_t ad7791_write_frequency(struct device *dev,
struct ad7791_state *st = iio_priv(indio_dev); struct ad7791_state *st = iio_priv(indio_dev);
int i, ret; int i, ret;
mutex_lock(&indio_dev->mlock); for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++)
if (iio_buffer_enabled(indio_dev)) { if (sysfs_streq(ad7791_sample_freq_avail[i], buf))
mutex_unlock(&indio_dev->mlock);
return -EBUSY;
}
mutex_unlock(&indio_dev->mlock);
ret = -EINVAL;
for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++) {
if (sysfs_streq(ad7791_sample_freq_avail[i], buf)) {
mutex_lock(&indio_dev->mlock);
st->filter &= ~AD7791_FILTER_RATE_MASK;
st->filter |= i;
ad_sd_write_reg(&st->sd, AD7791_REG_FILTER,
sizeof(st->filter), st->filter);
mutex_unlock(&indio_dev->mlock);
ret = 0;
break; break;
} if (i == ARRAY_SIZE(ad7791_sample_freq_avail))
} return -EINVAL;
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
st->filter &= ~AD7791_FILTER_RATE_MASK;
st->filter |= i;
ad_sd_write_reg(&st->sd, AD7791_REG_FILTER, sizeof(st->filter),
st->filter);
iio_device_release_direct_mode(indio_dev);
return ret ? ret : len; return len;
} }
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
...@@ -383,6 +375,7 @@ static int ad7791_probe(struct spi_device *spi) ...@@ -383,6 +375,7 @@ static int ad7791_probe(struct spi_device *spi)
spi_set_drvdata(spi, indio_dev); spi_set_drvdata(spi, indio_dev);
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->dev.of_node = spi->dev.of_node;
indio_dev->name = spi_get_device_id(spi)->name; indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = st->info->channels; indio_dev->channels = st->info->channels;
......
...@@ -369,13 +369,6 @@ static ssize_t ad7793_write_frequency(struct device *dev, ...@@ -369,13 +369,6 @@ static ssize_t ad7793_write_frequency(struct device *dev,
long lval; long lval;
int i, ret; int i, ret;
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev)) {
mutex_unlock(&indio_dev->mlock);
return -EBUSY;
}
mutex_unlock(&indio_dev->mlock);
ret = kstrtol(buf, 10, &lval); ret = kstrtol(buf, 10, &lval);
if (ret) if (ret)
return ret; return ret;
...@@ -383,20 +376,21 @@ static ssize_t ad7793_write_frequency(struct device *dev, ...@@ -383,20 +376,21 @@ static ssize_t ad7793_write_frequency(struct device *dev,
if (lval == 0) if (lval == 0)
return -EINVAL; return -EINVAL;
ret = -EINVAL;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
if (lval == st->chip_info->sample_freq_avail[i]) { if (lval == st->chip_info->sample_freq_avail[i])
mutex_lock(&indio_dev->mlock); break;
st->mode &= ~AD7793_MODE_RATE(-1); if (i == 16)
st->mode |= AD7793_MODE_RATE(i); return -EINVAL;
ad_sd_write_reg(&st->sd, AD7793_REG_MODE,
sizeof(st->mode), st->mode);
mutex_unlock(&indio_dev->mlock);
ret = 0;
}
return ret ? ret : len; ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
st->mode &= ~AD7793_MODE_RATE(-1);
st->mode |= AD7793_MODE_RATE(i);
ad_sd_write_reg(&st->sd, AD7793_REG_MODE, sizeof(st->mode), st->mode);
iio_device_release_direct_mode(indio_dev);
return len;
} }
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
...@@ -790,6 +784,7 @@ static int ad7793_probe(struct spi_device *spi) ...@@ -790,6 +784,7 @@ static int ad7793_probe(struct spi_device *spi)
spi_set_drvdata(spi, indio_dev); spi_set_drvdata(spi, indio_dev);
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->dev.of_node = spi->dev.of_node;
indio_dev->name = spi_get_device_id(spi)->name; indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = st->chip_info->channels; indio_dev->channels = st->chip_info->channels;
......
...@@ -122,7 +122,7 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p) ...@@ -122,7 +122,7 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p)
goto done; goto done;
iio_push_to_buffers_with_timestamp(indio_dev, st->data, iio_push_to_buffers_with_timestamp(indio_dev, st->data,
iio_get_time_ns()); iio_get_time_ns(indio_dev));
done: done:
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
...@@ -156,12 +156,11 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, ...@@ -156,12 +156,11 @@ static int ad7887_read_raw(struct iio_dev *indio_dev,
switch (m) { switch (m) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (iio_buffer_enabled(indio_dev)) if (ret)
ret = -EBUSY; return ret;
else ret = ad7887_scan_direct(st, chan->address);
ret = ad7887_scan_direct(st, chan->address); iio_device_release_direct_mode(indio_dev);
mutex_unlock(&indio_dev->mlock);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -265,6 +264,7 @@ static int ad7887_probe(struct spi_device *spi) ...@@ -265,6 +264,7 @@ static int ad7887_probe(struct spi_device *spi)
/* Estabilish that the iio_dev is a child of the spi device */ /* Estabilish that the iio_dev is a child of the spi device */
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->dev.of_node = spi->dev.of_node;
indio_dev->name = spi_get_device_id(spi)->name; indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->info = &ad7887_info; indio_dev->info = &ad7887_info;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
......
...@@ -181,7 +181,7 @@ static irqreturn_t ad7923_trigger_handler(int irq, void *p) ...@@ -181,7 +181,7 @@ static irqreturn_t ad7923_trigger_handler(int irq, void *p)
goto done; goto done;
iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf, iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
iio_get_time_ns()); iio_get_time_ns(indio_dev));
done: done:
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
...@@ -233,12 +233,11 @@ static int ad7923_read_raw(struct iio_dev *indio_dev, ...@@ -233,12 +233,11 @@ static int ad7923_read_raw(struct iio_dev *indio_dev,
switch (m) { switch (m) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (iio_buffer_enabled(indio_dev)) if (ret)
ret = -EBUSY; return ret;
else ret = ad7923_scan_direct(st, chan->address);
ret = ad7923_scan_direct(st, chan->address); iio_device_release_direct_mode(indio_dev);
mutex_unlock(&indio_dev->mlock);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -289,6 +288,7 @@ static int ad7923_probe(struct spi_device *spi) ...@@ -289,6 +288,7 @@ static int ad7923_probe(struct spi_device *spi)
indio_dev->name = spi_get_device_id(spi)->name; indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->dev.of_node = spi->dev.of_node;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = info->channels; indio_dev->channels = info->channels;
indio_dev->num_channels = info->num_channels; indio_dev->num_channels = info->num_channels;
......
...@@ -212,7 +212,7 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p) ...@@ -212,7 +212,7 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
goto out; goto out;
iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf, iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
iio_get_time_ns()); iio_get_time_ns(indio_dev));
out: out:
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
...@@ -282,12 +282,11 @@ static int ad799x_read_raw(struct iio_dev *indio_dev, ...@@ -282,12 +282,11 @@ static int ad799x_read_raw(struct iio_dev *indio_dev,
switch (m) { switch (m) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (iio_buffer_enabled(indio_dev)) if (ret)
ret = -EBUSY; return ret;
else ret = ad799x_scan_direct(st, chan->scan_index);
ret = ad799x_scan_direct(st, chan->scan_index); iio_device_release_direct_mode(indio_dev);
mutex_unlock(&indio_dev->mlock);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -395,11 +394,9 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev, ...@@ -395,11 +394,9 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev,
struct ad799x_state *st = iio_priv(indio_dev); struct ad799x_state *st = iio_priv(indio_dev);
int ret; int ret;
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (iio_buffer_enabled(indio_dev)) { if (ret)
ret = -EBUSY; return ret;
goto done;
}
if (state) if (state)
st->config |= BIT(chan->scan_index) << AD799X_CHANNEL_SHIFT; st->config |= BIT(chan->scan_index) << AD799X_CHANNEL_SHIFT;
...@@ -412,10 +409,7 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev, ...@@ -412,10 +409,7 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev,
st->config &= ~AD7998_ALERT_EN; st->config &= ~AD7998_ALERT_EN;
ret = ad799x_write_config(st, st->config); ret = ad799x_write_config(st, st->config);
iio_device_release_direct_mode(indio_dev);
done:
mutex_unlock(&indio_dev->mlock);
return ret; return ret;
} }
...@@ -508,7 +502,7 @@ static irqreturn_t ad799x_event_handler(int irq, void *private) ...@@ -508,7 +502,7 @@ static irqreturn_t ad799x_event_handler(int irq, void *private)
(i >> 1), (i >> 1),
IIO_EV_TYPE_THRESH, IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING), IIO_EV_DIR_FALLING),
iio_get_time_ns()); iio_get_time_ns(indio_dev));
} }
done: done:
...@@ -812,6 +806,7 @@ static int ad799x_probe(struct i2c_client *client, ...@@ -812,6 +806,7 @@ static int ad799x_probe(struct i2c_client *client,
st->client = client; st->client = client;
indio_dev->dev.parent = &client->dev; indio_dev->dev.parent = &client->dev;
indio_dev->dev.of_node = client->dev.of_node;
indio_dev->name = id->name; indio_dev->name = id->name;
indio_dev->info = st->chip_config->info; indio_dev->info = st->chip_config->info;
......
/*
* Copyright 2016 Broadcom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation (the "GPL").
*
* 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 version 2 (GPLv2) for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 (GPLv2) along with this source code.
*/
#include <linux/module.h>
#include <linux/of.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/iio/iio.h>
/* Below Register's are common to IPROC ADC and Touchscreen IP */
#define IPROC_REGCTL1 0x00
#define IPROC_REGCTL2 0x04
#define IPROC_INTERRUPT_THRES 0x08
#define IPROC_INTERRUPT_MASK 0x0c
#define IPROC_INTERRUPT_STATUS 0x10
#define IPROC_ANALOG_CONTROL 0x1c
#define IPROC_CONTROLLER_STATUS 0x14
#define IPROC_AUX_DATA 0x20
#define IPROC_SOFT_BYPASS_CONTROL 0x38
#define IPROC_SOFT_BYPASS_DATA 0x3C
/* IPROC ADC Channel register offsets */
#define IPROC_ADC_CHANNEL_REGCTL1 0x800
#define IPROC_ADC_CHANNEL_REGCTL2 0x804
#define IPROC_ADC_CHANNEL_STATUS 0x808
#define IPROC_ADC_CHANNEL_INTERRUPT_STATUS 0x80c
#define IPROC_ADC_CHANNEL_INTERRUPT_MASK 0x810
#define IPROC_ADC_CHANNEL_DATA 0x814
#define IPROC_ADC_CHANNEL_OFFSET 0x20
/* Bit definitions for IPROC_REGCTL2 */
#define IPROC_ADC_AUXIN_SCAN_ENA BIT(0)
#define IPROC_ADC_PWR_LDO BIT(5)
#define IPROC_ADC_PWR_ADC BIT(4)
#define IPROC_ADC_PWR_BG BIT(3)
#define IPROC_ADC_CONTROLLER_EN BIT(17)
/* Bit definitions for IPROC_INTERRUPT_MASK and IPROC_INTERRUPT_STATUS */
#define IPROC_ADC_AUXDATA_RDY_INTR BIT(3)
#define IPROC_ADC_INTR 9
#define IPROC_ADC_INTR_MASK (0xFF << IPROC_ADC_INTR)
/* Bit definitions for IPROC_ANALOG_CONTROL */
#define IPROC_ADC_CHANNEL_SEL 11
#define IPROC_ADC_CHANNEL_SEL_MASK (0x7 << IPROC_ADC_CHANNEL_SEL)
/* Bit definitions for IPROC_ADC_CHANNEL_REGCTL1 */
#define IPROC_ADC_CHANNEL_ROUNDS 0x2
#define IPROC_ADC_CHANNEL_ROUNDS_MASK (0x3F << IPROC_ADC_CHANNEL_ROUNDS)
#define IPROC_ADC_CHANNEL_MODE 0x1
#define IPROC_ADC_CHANNEL_MODE_MASK (0x1 << IPROC_ADC_CHANNEL_MODE)
#define IPROC_ADC_CHANNEL_MODE_TDM 0x1
#define IPROC_ADC_CHANNEL_MODE_SNAPSHOT 0x0
#define IPROC_ADC_CHANNEL_ENABLE 0x0
#define IPROC_ADC_CHANNEL_ENABLE_MASK 0x1
/* Bit definitions for IPROC_ADC_CHANNEL_REGCTL2 */
#define IPROC_ADC_CHANNEL_WATERMARK 0x0
#define IPROC_ADC_CHANNEL_WATERMARK_MASK \
(0x3F << IPROC_ADC_CHANNEL_WATERMARK)
#define IPROC_ADC_WATER_MARK_LEVEL 0x1
/* Bit definitions for IPROC_ADC_CHANNEL_STATUS */
#define IPROC_ADC_CHANNEL_DATA_LOST 0x0
#define IPROC_ADC_CHANNEL_DATA_LOST_MASK \
(0x0 << IPROC_ADC_CHANNEL_DATA_LOST)
#define IPROC_ADC_CHANNEL_VALID_ENTERIES 0x1
#define IPROC_ADC_CHANNEL_VALID_ENTERIES_MASK \
(0xFF << IPROC_ADC_CHANNEL_VALID_ENTERIES)
#define IPROC_ADC_CHANNEL_TOTAL_ENTERIES 0x9
#define IPROC_ADC_CHANNEL_TOTAL_ENTERIES_MASK \
(0xFF << IPROC_ADC_CHANNEL_TOTAL_ENTERIES)
/* Bit definitions for IPROC_ADC_CHANNEL_INTERRUPT_MASK */
#define IPROC_ADC_CHANNEL_WTRMRK_INTR 0x0
#define IPROC_ADC_CHANNEL_WTRMRK_INTR_MASK \
(0x1 << IPROC_ADC_CHANNEL_WTRMRK_INTR)
#define IPROC_ADC_CHANNEL_FULL_INTR 0x1
#define IPROC_ADC_CHANNEL_FULL_INTR_MASK \
(0x1 << IPROC_ADC_IPROC_ADC_CHANNEL_FULL_INTR)
#define IPROC_ADC_CHANNEL_EMPTY_INTR 0x2
#define IPROC_ADC_CHANNEL_EMPTY_INTR_MASK \
(0x1 << IPROC_ADC_CHANNEL_EMPTY_INTR)
#define IPROC_ADC_WATER_MARK_INTR_ENABLE 0x1
/* Number of time to retry a set of the interrupt mask reg */
#define IPROC_ADC_INTMASK_RETRY_ATTEMPTS 10
#define IPROC_ADC_READ_TIMEOUT (HZ*2)
#define iproc_adc_dbg_reg(dev, priv, reg) \
do { \
u32 val; \
regmap_read(priv->regmap, reg, &val); \
dev_dbg(dev, "%20s= 0x%08x\n", #reg, val); \
} while (0)
struct iproc_adc_priv {
struct regmap *regmap;
struct clk *adc_clk;
struct mutex mutex;
int irqno;
int chan_val;
int chan_id;
struct completion completion;
};
static void iproc_adc_reg_dump(struct iio_dev *indio_dev)
{
struct device *dev = &indio_dev->dev;
struct iproc_adc_priv *adc_priv = iio_priv(indio_dev);
iproc_adc_dbg_reg(dev, adc_priv, IPROC_REGCTL1);
iproc_adc_dbg_reg(dev, adc_priv, IPROC_REGCTL2);
iproc_adc_dbg_reg(dev, adc_priv, IPROC_INTERRUPT_THRES);
iproc_adc_dbg_reg(dev, adc_priv, IPROC_INTERRUPT_MASK);
iproc_adc_dbg_reg(dev, adc_priv, IPROC_INTERRUPT_STATUS);
iproc_adc_dbg_reg(dev, adc_priv, IPROC_CONTROLLER_STATUS);
iproc_adc_dbg_reg(dev, adc_priv, IPROC_ANALOG_CONTROL);
iproc_adc_dbg_reg(dev, adc_priv, IPROC_AUX_DATA);
iproc_adc_dbg_reg(dev, adc_priv, IPROC_SOFT_BYPASS_CONTROL);
iproc_adc_dbg_reg(dev, adc_priv, IPROC_SOFT_BYPASS_DATA);
}
static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data)
{
u32 channel_intr_status;
u32 intr_status;
u32 intr_mask;
struct iio_dev *indio_dev = data;
struct iproc_adc_priv *adc_priv = iio_priv(indio_dev);
/*
* This interrupt is shared with the touchscreen driver.
* Make sure this interrupt is intended for us.
* Handle only ADC channel specific interrupts.
*/
regmap_read(adc_priv->regmap, IPROC_INTERRUPT_STATUS, &intr_status);
regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &intr_mask);
intr_status = intr_status & intr_mask;
channel_intr_status = (intr_status & IPROC_ADC_INTR_MASK) >>
IPROC_ADC_INTR;
if (channel_intr_status)
return IRQ_WAKE_THREAD;
return IRQ_NONE;
}
static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data)
{
irqreturn_t retval = IRQ_NONE;
struct iproc_adc_priv *adc_priv;
struct iio_dev *indio_dev = data;
unsigned int valid_entries;
u32 intr_status;
u32 intr_channels;
u32 channel_status;
u32 ch_intr_status;
adc_priv = iio_priv(indio_dev);
regmap_read(adc_priv->regmap, IPROC_INTERRUPT_STATUS, &intr_status);
dev_dbg(&indio_dev->dev, "iproc_adc_interrupt_thread(),INTRPT_STS:%x\n",
intr_status);
intr_channels = (intr_status & IPROC_ADC_INTR_MASK) >> IPROC_ADC_INTR;
if (intr_channels) {
regmap_read(adc_priv->regmap,
IPROC_ADC_CHANNEL_INTERRUPT_STATUS +
IPROC_ADC_CHANNEL_OFFSET * adc_priv->chan_id,
&ch_intr_status);
if (ch_intr_status & IPROC_ADC_CHANNEL_WTRMRK_INTR_MASK) {
regmap_read(adc_priv->regmap,
IPROC_ADC_CHANNEL_STATUS +
IPROC_ADC_CHANNEL_OFFSET *
adc_priv->chan_id,
&channel_status);
valid_entries = ((channel_status &
IPROC_ADC_CHANNEL_VALID_ENTERIES_MASK) >>
IPROC_ADC_CHANNEL_VALID_ENTERIES);
if (valid_entries >= 1) {
regmap_read(adc_priv->regmap,
IPROC_ADC_CHANNEL_DATA +
IPROC_ADC_CHANNEL_OFFSET *
adc_priv->chan_id,
&adc_priv->chan_val);
complete(&adc_priv->completion);
} else {
dev_err(&indio_dev->dev,
"No data rcvd on channel %d\n",
adc_priv->chan_id);
}
regmap_write(adc_priv->regmap,
IPROC_ADC_CHANNEL_INTERRUPT_MASK +
IPROC_ADC_CHANNEL_OFFSET *
adc_priv->chan_id,
(ch_intr_status &
~(IPROC_ADC_CHANNEL_WTRMRK_INTR_MASK)));
}
regmap_write(adc_priv->regmap,
IPROC_ADC_CHANNEL_INTERRUPT_STATUS +
IPROC_ADC_CHANNEL_OFFSET * adc_priv->chan_id,
ch_intr_status);
regmap_write(adc_priv->regmap, IPROC_INTERRUPT_STATUS,
intr_channels);
retval = IRQ_HANDLED;
}
return retval;
}
static int iproc_adc_do_read(struct iio_dev *indio_dev,
int channel,
u16 *p_adc_data)
{
int read_len = 0;
u32 val;
u32 mask;
u32 val_check;
int failed_cnt = 0;
struct iproc_adc_priv *adc_priv = iio_priv(indio_dev);
mutex_lock(&adc_priv->mutex);
/*
* After a read is complete the ADC interrupts will be disabled so
* we can assume this section of code is safe from interrupts.
*/
adc_priv->chan_val = -1;
adc_priv->chan_id = channel;
reinit_completion(&adc_priv->completion);
/* Clear any pending interrupt */
regmap_update_bits(adc_priv->regmap, IPROC_INTERRUPT_STATUS,
IPROC_ADC_INTR_MASK | IPROC_ADC_AUXDATA_RDY_INTR,
((0x0 << channel) << IPROC_ADC_INTR) |
IPROC_ADC_AUXDATA_RDY_INTR);
/* Configure channel for snapshot mode and enable */
val = (BIT(IPROC_ADC_CHANNEL_ROUNDS) |
(IPROC_ADC_CHANNEL_MODE_SNAPSHOT << IPROC_ADC_CHANNEL_MODE) |
(0x1 << IPROC_ADC_CHANNEL_ENABLE));
mask = IPROC_ADC_CHANNEL_ROUNDS_MASK | IPROC_ADC_CHANNEL_MODE_MASK |
IPROC_ADC_CHANNEL_ENABLE_MASK;
regmap_update_bits(adc_priv->regmap, (IPROC_ADC_CHANNEL_REGCTL1 +
IPROC_ADC_CHANNEL_OFFSET * channel),
mask, val);
/* Set the Watermark for a channel */
regmap_update_bits(adc_priv->regmap, (IPROC_ADC_CHANNEL_REGCTL2 +
IPROC_ADC_CHANNEL_OFFSET * channel),
IPROC_ADC_CHANNEL_WATERMARK_MASK,
0x1);
/* Enable water mark interrupt */
regmap_update_bits(adc_priv->regmap, (IPROC_ADC_CHANNEL_INTERRUPT_MASK +
IPROC_ADC_CHANNEL_OFFSET *
channel),
IPROC_ADC_CHANNEL_WTRMRK_INTR_MASK,
IPROC_ADC_WATER_MARK_INTR_ENABLE);
regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &val);
/* Enable ADC interrupt for a channel */
val |= (BIT(channel) << IPROC_ADC_INTR);
regmap_write(adc_priv->regmap, IPROC_INTERRUPT_MASK, val);
/*
* There seems to be a very rare issue where writing to this register
* does not take effect. To work around the issue we will try multiple
* writes. In total we will spend about 10*10 = 100 us attempting this.
* Testing has shown that this may loop a few time, but we have never
* hit the full count.
*/
regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &val_check);
while (val_check != val) {
failed_cnt++;
if (failed_cnt > IPROC_ADC_INTMASK_RETRY_ATTEMPTS)
break;
udelay(10);
regmap_update_bits(adc_priv->regmap, IPROC_INTERRUPT_MASK,
IPROC_ADC_INTR_MASK,
((0x1 << channel) <<
IPROC_ADC_INTR));
regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &val_check);
}
if (failed_cnt) {
dev_dbg(&indio_dev->dev,
"IntMask failed (%d times)", failed_cnt);
if (failed_cnt > IPROC_ADC_INTMASK_RETRY_ATTEMPTS) {
dev_err(&indio_dev->dev,
"IntMask set failed. Read will likely fail.");
read_len = -EIO;
goto adc_err;
};
}
regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &val_check);
if (wait_for_completion_timeout(&adc_priv->completion,
IPROC_ADC_READ_TIMEOUT) > 0) {
/* Only the lower 16 bits are relevant */
*p_adc_data = adc_priv->chan_val & 0xFFFF;
read_len = sizeof(*p_adc_data);
} else {
/*
* We never got the interrupt, something went wrong.
* Perhaps the interrupt may still be coming, we do not want
* that now. Lets disable the ADC interrupt, and clear the
* status to put it back in to normal state.
*/
read_len = -ETIMEDOUT;
goto adc_err;
}
mutex_unlock(&adc_priv->mutex);
return read_len;
adc_err:
regmap_update_bits(adc_priv->regmap, IPROC_INTERRUPT_MASK,
IPROC_ADC_INTR_MASK,
((0x0 << channel) << IPROC_ADC_INTR));
regmap_update_bits(adc_priv->regmap, IPROC_INTERRUPT_STATUS,
IPROC_ADC_INTR_MASK,
((0x0 << channel) << IPROC_ADC_INTR));
dev_err(&indio_dev->dev, "Timed out waiting for ADC data!\n");
iproc_adc_reg_dump(indio_dev);
mutex_unlock(&adc_priv->mutex);
return read_len;
}
static int iproc_adc_enable(struct iio_dev *indio_dev)
{
u32 val;
u32 channel_id;
struct iproc_adc_priv *adc_priv = iio_priv(indio_dev);
int ret;
/* Set i_amux = 3b'000, select channel 0 */
ret = regmap_update_bits(adc_priv->regmap, IPROC_ANALOG_CONTROL,
IPROC_ADC_CHANNEL_SEL_MASK, 0);
if (ret) {
dev_err(&indio_dev->dev,
"failed to write IPROC_ANALOG_CONTROL %d\n", ret);
return ret;
}
adc_priv->chan_val = -1;
/*
* PWR up LDO, ADC, and Band Gap (0 to enable)
* Also enable ADC controller (set high)
*/
ret = regmap_read(adc_priv->regmap, IPROC_REGCTL2, &val);
if (ret) {
dev_err(&indio_dev->dev,
"failed to read IPROC_REGCTL2 %d\n", ret);
return ret;
}
val &= ~(IPROC_ADC_PWR_LDO | IPROC_ADC_PWR_ADC | IPROC_ADC_PWR_BG);
ret = regmap_write(adc_priv->regmap, IPROC_REGCTL2, val);
if (ret) {
dev_err(&indio_dev->dev,
"failed to write IPROC_REGCTL2 %d\n", ret);
return ret;
}
ret = regmap_read(adc_priv->regmap, IPROC_REGCTL2, &val);
if (ret) {
dev_err(&indio_dev->dev,
"failed to read IPROC_REGCTL2 %d\n", ret);
return ret;
}
val |= IPROC_ADC_CONTROLLER_EN;
ret = regmap_write(adc_priv->regmap, IPROC_REGCTL2, val);
if (ret) {
dev_err(&indio_dev->dev,
"failed to write IPROC_REGCTL2 %d\n", ret);
return ret;
}
for (channel_id = 0; channel_id < indio_dev->num_channels;
channel_id++) {
ret = regmap_write(adc_priv->regmap,
IPROC_ADC_CHANNEL_INTERRUPT_MASK +
IPROC_ADC_CHANNEL_OFFSET * channel_id, 0);
if (ret) {
dev_err(&indio_dev->dev,
"failed to write ADC_CHANNEL_INTERRUPT_MASK %d\n",
ret);
return ret;
}
ret = regmap_write(adc_priv->regmap,
IPROC_ADC_CHANNEL_INTERRUPT_STATUS +
IPROC_ADC_CHANNEL_OFFSET * channel_id, 0);
if (ret) {
dev_err(&indio_dev->dev,
"failed to write ADC_CHANNEL_INTERRUPT_STATUS %d\n",
ret);
return ret;
}
}
return 0;
}
static void iproc_adc_disable(struct iio_dev *indio_dev)
{
u32 val;
int ret;
struct iproc_adc_priv *adc_priv = iio_priv(indio_dev);
ret = regmap_read(adc_priv->regmap, IPROC_REGCTL2, &val);
if (ret) {
dev_err(&indio_dev->dev,
"failed to read IPROC_REGCTL2 %d\n", ret);
return;
}
val &= ~IPROC_ADC_CONTROLLER_EN;
ret = regmap_write(adc_priv->regmap, IPROC_REGCTL2, val);
if (ret) {
dev_err(&indio_dev->dev,
"failed to write IPROC_REGCTL2 %d\n", ret);
return;
}
}
static int iproc_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val,
int *val2,
long mask)
{
u16 adc_data;
int err;
switch (mask) {
case IIO_CHAN_INFO_RAW:
err = iproc_adc_do_read(indio_dev, chan->channel, &adc_data);
if (err < 0)
return err;
*val = adc_data;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
*val = 1800;
*val2 = 10;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
default:
return -EINVAL;
}
}
static const struct iio_info iproc_adc_iio_info = {
.read_raw = &iproc_adc_read_raw,
.driver_module = THIS_MODULE,
};
#define IPROC_ADC_CHANNEL(_index, _id) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = _index, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.datasheet_name = _id, \
}
static const struct iio_chan_spec iproc_adc_iio_channels[] = {
IPROC_ADC_CHANNEL(0, "adc0"),
IPROC_ADC_CHANNEL(1, "adc1"),
IPROC_ADC_CHANNEL(2, "adc2"),
IPROC_ADC_CHANNEL(3, "adc3"),
IPROC_ADC_CHANNEL(4, "adc4"),
IPROC_ADC_CHANNEL(5, "adc5"),
IPROC_ADC_CHANNEL(6, "adc6"),
IPROC_ADC_CHANNEL(7, "adc7"),
};
static int iproc_adc_probe(struct platform_device *pdev)
{
struct iproc_adc_priv *adc_priv;
struct iio_dev *indio_dev = NULL;
int ret;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(*adc_priv));
if (!indio_dev) {
dev_err(&pdev->dev, "failed to allocate iio device\n");
return -ENOMEM;
}
adc_priv = iio_priv(indio_dev);
platform_set_drvdata(pdev, indio_dev);
mutex_init(&adc_priv->mutex);
init_completion(&adc_priv->completion);
adc_priv->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"adc-syscon");
if (IS_ERR(adc_priv->regmap)) {
dev_err(&pdev->dev, "failed to get handle for tsc syscon\n");
ret = PTR_ERR(adc_priv->regmap);
return ret;
}
adc_priv->adc_clk = devm_clk_get(&pdev->dev, "tsc_clk");
if (IS_ERR(adc_priv->adc_clk)) {
dev_err(&pdev->dev,
"failed getting clock tsc_clk\n");
ret = PTR_ERR(adc_priv->adc_clk);
return ret;
}
adc_priv->irqno = platform_get_irq(pdev, 0);
if (adc_priv->irqno <= 0) {
dev_err(&pdev->dev, "platform_get_irq failed\n");
ret = -ENODEV;
return ret;
}
ret = regmap_update_bits(adc_priv->regmap, IPROC_REGCTL2,
IPROC_ADC_AUXIN_SCAN_ENA, 0);
if (ret) {
dev_err(&pdev->dev, "failed to write IPROC_REGCTL2 %d\n", ret);
return ret;
}
ret = devm_request_threaded_irq(&pdev->dev, adc_priv->irqno,
iproc_adc_interrupt_thread,
iproc_adc_interrupt_handler,
IRQF_SHARED, "iproc-adc", indio_dev);
if (ret) {
dev_err(&pdev->dev, "request_irq error %d\n", ret);
return ret;
}
ret = clk_prepare_enable(adc_priv->adc_clk);
if (ret) {
dev_err(&pdev->dev,
"clk_prepare_enable failed %d\n", ret);
return ret;
}
ret = iproc_adc_enable(indio_dev);
if (ret) {
dev_err(&pdev->dev, "failed to enable adc %d\n", ret);
goto err_adc_enable;
}
indio_dev->name = "iproc-static-adc";
indio_dev->dev.parent = &pdev->dev;
indio_dev->dev.of_node = pdev->dev.of_node;
indio_dev->info = &iproc_adc_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = iproc_adc_iio_channels;
indio_dev->num_channels = ARRAY_SIZE(iproc_adc_iio_channels);
ret = iio_device_register(indio_dev);
if (ret) {
dev_err(&pdev->dev, "iio_device_register failed:err %d\n", ret);
goto err_clk;
}
return 0;
err_clk:
iproc_adc_disable(indio_dev);
err_adc_enable:
clk_disable_unprepare(adc_priv->adc_clk);
return ret;
}
static int iproc_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct iproc_adc_priv *adc_priv = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
iproc_adc_disable(indio_dev);
clk_disable_unprepare(adc_priv->adc_clk);
return 0;
}
static const struct of_device_id iproc_adc_of_match[] = {
{.compatible = "brcm,iproc-static-adc", },
{ },
};
MODULE_DEVICE_TABLE(of, iproc_adc_of_match);
static struct platform_driver iproc_adc_driver = {
.probe = iproc_adc_probe,
.remove = iproc_adc_remove,
.driver = {
.name = "iproc-static-adc",
.of_match_table = of_match_ptr(iproc_adc_of_match),
},
};
module_platform_driver(iproc_adc_driver);
MODULE_DESCRIPTION("Broadcom iProc ADC controller driver");
MODULE_AUTHOR("Raveendra Padasalagi <raveendra.padasalagi@broadcom.com>");
MODULE_LICENSE("GPL v2");
...@@ -186,7 +186,7 @@ static irqreturn_t cc10001_adc_trigger_h(int irq, void *p) ...@@ -186,7 +186,7 @@ static irqreturn_t cc10001_adc_trigger_h(int irq, void *p)
if (!sample_invalid) if (!sample_invalid)
iio_push_to_buffers_with_timestamp(indio_dev, data, iio_push_to_buffers_with_timestamp(indio_dev, data,
iio_get_time_ns()); iio_get_time_ns(indio_dev));
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED; return IRQ_HANDLED;
......
...@@ -400,7 +400,7 @@ static void hi8435_iio_push_event(struct iio_dev *idev, unsigned int val) ...@@ -400,7 +400,7 @@ static void hi8435_iio_push_event(struct iio_dev *idev, unsigned int val)
iio_push_event(idev, iio_push_event(idev,
IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i, IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i,
IIO_EV_TYPE_THRESH, dir), IIO_EV_TYPE_THRESH, dir),
iio_get_time_ns()); iio_get_time_ns(idev));
} }
} }
...@@ -455,6 +455,7 @@ static int hi8435_probe(struct spi_device *spi) ...@@ -455,6 +455,7 @@ static int hi8435_probe(struct spi_device *spi)
mutex_init(&priv->lock); mutex_init(&priv->lock);
idev->dev.parent = &spi->dev; idev->dev.parent = &spi->dev;
idev->dev.of_node = spi->dev.of_node;
idev->name = spi_get_device_id(spi)->name; idev->name = spi_get_device_id(spi)->name;
idev->modes = INDIO_DIRECT_MODE; idev->modes = INDIO_DIRECT_MODE;
idev->info = &hi8435_info; idev->info = &hi8435_info;
......
...@@ -465,7 +465,7 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) ...@@ -465,7 +465,7 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev)
s64 time_a, time_b; s64 time_a, time_b;
unsigned int alert; unsigned int alert;
time_a = iio_get_time_ns(); time_a = iio_get_time_ns(indio_dev);
/* /*
* Because the timer thread and the chip conversion clock * Because the timer thread and the chip conversion clock
...@@ -504,7 +504,7 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) ...@@ -504,7 +504,7 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev)
data[i++] = val; data[i++] = val;
} }
time_b = iio_get_time_ns(); time_b = iio_get_time_ns(indio_dev);
iio_push_to_buffers_with_timestamp(indio_dev, iio_push_to_buffers_with_timestamp(indio_dev,
(unsigned int *)data, time_a); (unsigned int *)data, time_a);
...@@ -554,7 +554,7 @@ static int ina2xx_buffer_enable(struct iio_dev *indio_dev) ...@@ -554,7 +554,7 @@ static int ina2xx_buffer_enable(struct iio_dev *indio_dev)
dev_dbg(&indio_dev->dev, "Async readout mode: %d\n", dev_dbg(&indio_dev->dev, "Async readout mode: %d\n",
chip->allow_async_readout); chip->allow_async_readout);
chip->prev_ns = iio_get_time_ns(); chip->prev_ns = iio_get_time_ns(indio_dev);
chip->task = kthread_run(ina2xx_capture_thread, (void *)indio_dev, chip->task = kthread_run(ina2xx_capture_thread, (void *)indio_dev,
"%s:%d-%uus", indio_dev->name, indio_dev->id, "%s:%d-%uus", indio_dev->name, indio_dev->id,
...@@ -691,6 +691,7 @@ static int ina2xx_probe(struct i2c_client *client, ...@@ -691,6 +691,7 @@ static int ina2xx_probe(struct i2c_client *client,
indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
indio_dev->dev.parent = &client->dev; indio_dev->dev.parent = &client->dev;
indio_dev->dev.of_node = client->dev.of_node;
indio_dev->channels = ina2xx_channels; indio_dev->channels = ina2xx_channels;
indio_dev->num_channels = ARRAY_SIZE(ina2xx_channels); indio_dev->num_channels = ARRAY_SIZE(ina2xx_channels);
indio_dev->name = id->name; indio_dev->name = id->name;
......
...@@ -426,6 +426,7 @@ static int max1027_probe(struct spi_device *spi) ...@@ -426,6 +426,7 @@ static int max1027_probe(struct spi_device *spi)
indio_dev->name = spi_get_device_id(spi)->name; indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->dev.of_node = spi->dev.of_node;
indio_dev->info = &max1027_info; indio_dev->info = &max1027_info;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = st->info->channels; indio_dev->channels = st->info->channels;
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
...@@ -788,7 +790,7 @@ static irqreturn_t max1363_event_handler(int irq, void *private) ...@@ -788,7 +790,7 @@ static irqreturn_t max1363_event_handler(int irq, void *private)
{ {
struct iio_dev *indio_dev = private; struct iio_dev *indio_dev = private;
struct max1363_state *st = iio_priv(indio_dev); struct max1363_state *st = iio_priv(indio_dev);
s64 timestamp = iio_get_time_ns(); s64 timestamp = iio_get_time_ns(indio_dev);
unsigned long mask, loc; unsigned long mask, loc;
u8 rx; u8 rx;
u8 tx[2] = { st->setupbyte, u8 tx[2] = { st->setupbyte,
...@@ -1506,7 +1508,8 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p) ...@@ -1506,7 +1508,8 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p)
if (b_sent < 0) if (b_sent < 0)
goto done_free; goto done_free;
iio_push_to_buffers_with_timestamp(indio_dev, rxbuf, iio_get_time_ns()); iio_push_to_buffers_with_timestamp(indio_dev, rxbuf,
iio_get_time_ns(indio_dev));
done_free: done_free:
kfree(rxbuf); kfree(rxbuf);
...@@ -1516,6 +1519,56 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p) ...@@ -1516,6 +1519,56 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
#ifdef CONFIG_OF
#define MAX1363_COMPATIBLE(of_compatible, cfg) { \
.compatible = of_compatible, \
.data = &max1363_chip_info_tbl[cfg], \
}
static const struct of_device_id max1363_of_match[] = {
MAX1363_COMPATIBLE("maxim,max1361", max1361),
MAX1363_COMPATIBLE("maxim,max1362", max1362),
MAX1363_COMPATIBLE("maxim,max1363", max1363),
MAX1363_COMPATIBLE("maxim,max1364", max1364),
MAX1363_COMPATIBLE("maxim,max1036", max1036),
MAX1363_COMPATIBLE("maxim,max1037", max1037),
MAX1363_COMPATIBLE("maxim,max1038", max1038),
MAX1363_COMPATIBLE("maxim,max1039", max1039),
MAX1363_COMPATIBLE("maxim,max1136", max1136),
MAX1363_COMPATIBLE("maxim,max1137", max1137),
MAX1363_COMPATIBLE("maxim,max1138", max1138),
MAX1363_COMPATIBLE("maxim,max1139", max1139),
MAX1363_COMPATIBLE("maxim,max1236", max1236),
MAX1363_COMPATIBLE("maxim,max1237", max1237),
MAX1363_COMPATIBLE("maxim,max1238", max1238),
MAX1363_COMPATIBLE("maxim,max1239", max1239),
MAX1363_COMPATIBLE("maxim,max11600", max11600),
MAX1363_COMPATIBLE("maxim,max11601", max11601),
MAX1363_COMPATIBLE("maxim,max11602", max11602),
MAX1363_COMPATIBLE("maxim,max11603", max11603),
MAX1363_COMPATIBLE("maxim,max11604", max11604),
MAX1363_COMPATIBLE("maxim,max11605", max11605),
MAX1363_COMPATIBLE("maxim,max11606", max11606),
MAX1363_COMPATIBLE("maxim,max11607", max11607),
MAX1363_COMPATIBLE("maxim,max11608", max11608),
MAX1363_COMPATIBLE("maxim,max11609", max11609),
MAX1363_COMPATIBLE("maxim,max11610", max11610),
MAX1363_COMPATIBLE("maxim,max11611", max11611),
MAX1363_COMPATIBLE("maxim,max11612", max11612),
MAX1363_COMPATIBLE("maxim,max11613", max11613),
MAX1363_COMPATIBLE("maxim,max11614", max11614),
MAX1363_COMPATIBLE("maxim,max11615", max11615),
MAX1363_COMPATIBLE("maxim,max11616", max11616),
MAX1363_COMPATIBLE("maxim,max11617", max11617),
MAX1363_COMPATIBLE("maxim,max11644", max11644),
MAX1363_COMPATIBLE("maxim,max11645", max11645),
MAX1363_COMPATIBLE("maxim,max11646", max11646),
MAX1363_COMPATIBLE("maxim,max11647", max11647),
{ /* sentinel */ }
};
#endif
static int max1363_probe(struct i2c_client *client, static int max1363_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -1523,6 +1576,7 @@ static int max1363_probe(struct i2c_client *client, ...@@ -1523,6 +1576,7 @@ static int max1363_probe(struct i2c_client *client,
struct max1363_state *st; struct max1363_state *st;
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct regulator *vref; struct regulator *vref;
const struct of_device_id *match;
indio_dev = devm_iio_device_alloc(&client->dev, indio_dev = devm_iio_device_alloc(&client->dev,
sizeof(struct max1363_state)); sizeof(struct max1363_state));
...@@ -1549,7 +1603,12 @@ static int max1363_probe(struct i2c_client *client, ...@@ -1549,7 +1603,12 @@ static int max1363_probe(struct i2c_client *client,
/* this is only used for device removal purposes */ /* this is only used for device removal purposes */
i2c_set_clientdata(client, indio_dev); i2c_set_clientdata(client, indio_dev);
st->chip_info = &max1363_chip_info_tbl[id->driver_data]; match = of_match_device(of_match_ptr(max1363_of_match),
&client->dev);
if (match)
st->chip_info = of_device_get_match_data(&client->dev);
else
st->chip_info = &max1363_chip_info_tbl[id->driver_data];
st->client = client; st->client = client;
st->vref_uv = st->chip_info->int_vref_mv * 1000; st->vref_uv = st->chip_info->int_vref_mv * 1000;
...@@ -1587,6 +1646,7 @@ static int max1363_probe(struct i2c_client *client, ...@@ -1587,6 +1646,7 @@ static int max1363_probe(struct i2c_client *client,
/* Establish that the iio_dev is a child of the i2c device */ /* Establish that the iio_dev is a child of the i2c device */
indio_dev->dev.parent = &client->dev; indio_dev->dev.parent = &client->dev;
indio_dev->dev.of_node = client->dev.of_node;
indio_dev->name = id->name; indio_dev->name = id->name;
indio_dev->channels = st->chip_info->channels; indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels; indio_dev->num_channels = st->chip_info->num_channels;
...@@ -1692,6 +1752,7 @@ MODULE_DEVICE_TABLE(i2c, max1363_id); ...@@ -1692,6 +1752,7 @@ MODULE_DEVICE_TABLE(i2c, max1363_id);
static struct i2c_driver max1363_driver = { static struct i2c_driver max1363_driver = {
.driver = { .driver = {
.name = "max1363", .name = "max1363",
.of_match_table = of_match_ptr(max1363_of_match),
}, },
.probe = max1363_probe, .probe = max1363_probe,
.remove = max1363_remove, .remove = max1363_remove,
......
...@@ -308,6 +308,7 @@ static int mcp320x_probe(struct spi_device *spi) ...@@ -308,6 +308,7 @@ static int mcp320x_probe(struct spi_device *spi)
adc->spi = spi; adc->spi = spi;
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->dev.of_node = spi->dev.of_node;
indio_dev->name = spi_get_device_id(spi)->name; indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &mcp320x_info; indio_dev->info = &mcp320x_info;
......
...@@ -352,6 +352,7 @@ static int mcp3422_probe(struct i2c_client *client, ...@@ -352,6 +352,7 @@ static int mcp3422_probe(struct i2c_client *client,
mutex_init(&adc->lock); mutex_init(&adc->lock);
indio_dev->dev.parent = &client->dev; indio_dev->dev.parent = &client->dev;
indio_dev->dev.of_node = client->dev.of_node;
indio_dev->name = dev_name(&client->dev); indio_dev->name = dev_name(&client->dev);
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &mcp3422_info; indio_dev->info = &mcp3422_info;
......
...@@ -373,13 +373,6 @@ static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc) ...@@ -373,13 +373,6 @@ static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc)
return LRADC_CTRL0_MX28_PLATE_MASK; return LRADC_CTRL0_MX28_PLATE_MASK;
} }
static u32 mxs_lradc_irq_en_mask(struct mxs_lradc *lradc)
{
if (lradc->soc == IMX23_LRADC)
return LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK;
return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK;
}
static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc) static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc)
{ {
if (lradc->soc == IMX23_LRADC) if (lradc->soc == IMX23_LRADC)
...@@ -1120,18 +1113,16 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc) ...@@ -1120,18 +1113,16 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc)
{ {
struct input_dev *input; struct input_dev *input;
struct device *dev = lradc->dev; struct device *dev = lradc->dev;
int ret;
if (!lradc->use_touchscreen) if (!lradc->use_touchscreen)
return 0; return 0;
input = input_allocate_device(); input = devm_input_allocate_device(dev);
if (!input) if (!input)
return -ENOMEM; return -ENOMEM;
input->name = DRIVER_NAME; input->name = DRIVER_NAME;
input->id.bustype = BUS_HOST; input->id.bustype = BUS_HOST;
input->dev.parent = dev;
input->open = mxs_lradc_ts_open; input->open = mxs_lradc_ts_open;
input->close = mxs_lradc_ts_close; input->close = mxs_lradc_ts_close;
...@@ -1146,20 +1137,8 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc) ...@@ -1146,20 +1137,8 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc)
lradc->ts_input = input; lradc->ts_input = input;
input_set_drvdata(input, lradc); input_set_drvdata(input, lradc);
ret = input_register_device(input);
if (ret)
input_free_device(lradc->ts_input);
return ret;
}
static void mxs_lradc_ts_unregister(struct mxs_lradc *lradc)
{
if (!lradc->use_touchscreen)
return;
mxs_lradc_disable_ts(lradc); return input_register_device(input);
input_unregister_device(lradc->ts_input);
} }
/* /*
...@@ -1510,7 +1489,9 @@ static void mxs_lradc_hw_stop(struct mxs_lradc *lradc) ...@@ -1510,7 +1489,9 @@ static void mxs_lradc_hw_stop(struct mxs_lradc *lradc)
{ {
int i; int i;
mxs_lradc_reg_clear(lradc, mxs_lradc_irq_en_mask(lradc), LRADC_CTRL1); mxs_lradc_reg_clear(lradc,
lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET,
LRADC_CTRL1);
for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++) for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++)
mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(i)); mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(i));
...@@ -1721,13 +1702,11 @@ static int mxs_lradc_probe(struct platform_device *pdev) ...@@ -1721,13 +1702,11 @@ static int mxs_lradc_probe(struct platform_device *pdev)
ret = iio_device_register(iio); ret = iio_device_register(iio);
if (ret) { if (ret) {
dev_err(dev, "Failed to register IIO device\n"); dev_err(dev, "Failed to register IIO device\n");
goto err_ts; return ret;
} }
return 0; return 0;
err_ts:
mxs_lradc_ts_unregister(lradc);
err_ts_register: err_ts_register:
mxs_lradc_hw_stop(lradc); mxs_lradc_hw_stop(lradc);
err_dev: err_dev:
...@@ -1745,7 +1724,6 @@ static int mxs_lradc_remove(struct platform_device *pdev) ...@@ -1745,7 +1724,6 @@ static int mxs_lradc_remove(struct platform_device *pdev)
struct mxs_lradc *lradc = iio_priv(iio); struct mxs_lradc *lradc = iio_priv(iio);
iio_device_unregister(iio); iio_device_unregister(iio);
mxs_lradc_ts_unregister(lradc);
mxs_lradc_hw_stop(lradc); mxs_lradc_hw_stop(lradc);
mxs_lradc_trigger_remove(iio); mxs_lradc_trigger_remove(iio);
iio_triggered_buffer_cleanup(iio); iio_triggered_buffer_cleanup(iio);
......
...@@ -79,10 +79,29 @@ static const struct iio_chan_spec nau7802_chan_array[] = { ...@@ -79,10 +79,29 @@ static const struct iio_chan_spec nau7802_chan_array[] = {
static const u16 nau7802_sample_freq_avail[] = {10, 20, 40, 80, static const u16 nau7802_sample_freq_avail[] = {10, 20, 40, 80,
10, 10, 10, 320}; 10, 10, 10, 320};
static ssize_t nau7802_show_scales(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct nau7802_state *st = iio_priv(dev_to_iio_dev(dev));
int i, len = 0;
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
len += scnprintf(buf + len, PAGE_SIZE - len, "0.%09d ",
st->scale_avail[i]);
buf[len-1] = '\n';
return len;
}
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 40 80 320"); static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 40 80 320");
static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO, nau7802_show_scales,
NULL, 0);
static struct attribute *nau7802_attributes[] = { static struct attribute *nau7802_attributes[] = {
&iio_const_attr_sampling_frequency_available.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_in_voltage_scale_available.dev_attr.attr,
NULL NULL
}; };
...@@ -414,6 +433,7 @@ static int nau7802_probe(struct i2c_client *client, ...@@ -414,6 +433,7 @@ static int nau7802_probe(struct i2c_client *client,
i2c_set_clientdata(client, indio_dev); i2c_set_clientdata(client, indio_dev);
indio_dev->dev.parent = &client->dev; indio_dev->dev.parent = &client->dev;
indio_dev->dev.of_node = client->dev.of_node;
indio_dev->name = dev_name(&client->dev); indio_dev->name = dev_name(&client->dev);
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &nau7802_info; indio_dev->info = &nau7802_info;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/acpi.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
...@@ -138,7 +139,8 @@ static irqreturn_t adc081c_trigger_handler(int irq, void *p) ...@@ -138,7 +139,8 @@ static irqreturn_t adc081c_trigger_handler(int irq, void *p)
if (ret < 0) if (ret < 0)
goto out; goto out;
buf[0] = ret; buf[0] = ret;
iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); iio_push_to_buffers_with_timestamp(indio_dev, buf,
iio_get_time_ns(indio_dev));
out: out:
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -149,12 +151,24 @@ static int adc081c_probe(struct i2c_client *client, ...@@ -149,12 +151,24 @@ static int adc081c_probe(struct i2c_client *client,
{ {
struct iio_dev *iio; struct iio_dev *iio;
struct adc081c *adc; struct adc081c *adc;
struct adcxx1c_model *model = &adcxx1c_models[id->driver_data]; struct adcxx1c_model *model;
int err; int err;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (ACPI_COMPANION(&client->dev)) {
const struct acpi_device_id *ad_id;
ad_id = acpi_match_device(client->dev.driver->acpi_match_table,
&client->dev);
if (!ad_id)
return -ENODEV;
model = &adcxx1c_models[ad_id->driver_data];
} else {
model = &adcxx1c_models[id->driver_data];
}
iio = devm_iio_device_alloc(&client->dev, sizeof(*adc)); iio = devm_iio_device_alloc(&client->dev, sizeof(*adc));
if (!iio) if (!iio)
return -ENOMEM; return -ENOMEM;
...@@ -172,6 +186,7 @@ static int adc081c_probe(struct i2c_client *client, ...@@ -172,6 +186,7 @@ static int adc081c_probe(struct i2c_client *client,
return err; return err;
iio->dev.parent = &client->dev; iio->dev.parent = &client->dev;
iio->dev.of_node = client->dev.of_node;
iio->name = dev_name(&client->dev); iio->name = dev_name(&client->dev);
iio->modes = INDIO_DIRECT_MODE; iio->modes = INDIO_DIRECT_MODE;
iio->info = &adc081c_info; iio->info = &adc081c_info;
...@@ -231,10 +246,21 @@ static const struct of_device_id adc081c_of_match[] = { ...@@ -231,10 +246,21 @@ static const struct of_device_id adc081c_of_match[] = {
MODULE_DEVICE_TABLE(of, adc081c_of_match); MODULE_DEVICE_TABLE(of, adc081c_of_match);
#endif #endif
#ifdef CONFIG_ACPI
static const struct acpi_device_id adc081c_acpi_match[] = {
{ "ADC081C", ADC081C },
{ "ADC101C", ADC101C },
{ "ADC121C", ADC121C },
{ }
};
MODULE_DEVICE_TABLE(acpi, adc081c_acpi_match);
#endif
static struct i2c_driver adc081c_driver = { static struct i2c_driver adc081c_driver = {
.driver = { .driver = {
.name = "adc081c", .name = "adc081c",
.of_match_table = of_match_ptr(adc081c_of_match), .of_match_table = of_match_ptr(adc081c_of_match),
.acpi_match_table = ACPI_PTR(adc081c_acpi_match),
}, },
.probe = adc081c_probe, .probe = adc081c_probe,
.remove = adc081c_remove, .remove = adc081c_remove,
......
...@@ -194,6 +194,7 @@ static int adc0832_probe(struct spi_device *spi) ...@@ -194,6 +194,7 @@ static int adc0832_probe(struct spi_device *spi)
indio_dev->name = spi_get_device_id(spi)->name; indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->dev.of_node = spi->dev.of_node;
indio_dev->info = &adc0832_info; indio_dev->info = &adc0832_info;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
......
...@@ -150,6 +150,7 @@ static int adc128_probe(struct spi_device *spi) ...@@ -150,6 +150,7 @@ static int adc128_probe(struct spi_device *spi)
spi_set_drvdata(spi, indio_dev); spi_set_drvdata(spi, indio_dev);
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->dev.of_node = spi->dev.of_node;
indio_dev->name = spi_get_device_id(spi)->name; indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &adc128_info; indio_dev->info = &adc128_info;
......
...@@ -55,6 +55,11 @@ ...@@ -55,6 +55,11 @@
#define ADS1015_DEFAULT_DATA_RATE 4 #define ADS1015_DEFAULT_DATA_RATE 4
#define ADS1015_DEFAULT_CHAN 0 #define ADS1015_DEFAULT_CHAN 0
enum {
ADS1015,
ADS1115,
};
enum ads1015_channels { enum ads1015_channels {
ADS1015_AIN0_AIN1 = 0, ADS1015_AIN0_AIN1 = 0,
ADS1015_AIN0_AIN3, ADS1015_AIN0_AIN3,
...@@ -71,6 +76,10 @@ static const unsigned int ads1015_data_rate[] = { ...@@ -71,6 +76,10 @@ static const unsigned int ads1015_data_rate[] = {
128, 250, 490, 920, 1600, 2400, 3300, 3300 128, 250, 490, 920, 1600, 2400, 3300, 3300
}; };
static const unsigned int ads1115_data_rate[] = {
8, 16, 32, 64, 128, 250, 475, 860
};
static const struct { static const struct {
int scale; int scale;
int uscale; int uscale;
...@@ -101,6 +110,7 @@ static const struct { ...@@ -101,6 +110,7 @@ static const struct {
.shift = 4, \ .shift = 4, \
.endianness = IIO_CPU, \ .endianness = IIO_CPU, \
}, \ }, \
.datasheet_name = "AIN"#_chan, \
} }
#define ADS1015_V_DIFF_CHAN(_chan, _chan2, _addr) { \ #define ADS1015_V_DIFF_CHAN(_chan, _chan2, _addr) { \
...@@ -121,6 +131,45 @@ static const struct { ...@@ -121,6 +131,45 @@ static const struct {
.shift = 4, \ .shift = 4, \
.endianness = IIO_CPU, \ .endianness = IIO_CPU, \
}, \ }, \
.datasheet_name = "AIN"#_chan"-AIN"#_chan2, \
}
#define ADS1115_V_CHAN(_chan, _addr) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.address = _addr, \
.channel = _chan, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.scan_index = _addr, \
.scan_type = { \
.sign = 's', \
.realbits = 16, \
.storagebits = 16, \
.endianness = IIO_CPU, \
}, \
.datasheet_name = "AIN"#_chan, \
}
#define ADS1115_V_DIFF_CHAN(_chan, _chan2, _addr) { \
.type = IIO_VOLTAGE, \
.differential = 1, \
.indexed = 1, \
.address = _addr, \
.channel = _chan, \
.channel2 = _chan2, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.scan_index = _addr, \
.scan_type = { \
.sign = 's', \
.realbits = 16, \
.storagebits = 16, \
.endianness = IIO_CPU, \
}, \
.datasheet_name = "AIN"#_chan"-AIN"#_chan2, \
} }
struct ads1015_data { struct ads1015_data {
...@@ -131,6 +180,8 @@ struct ads1015_data { ...@@ -131,6 +180,8 @@ struct ads1015_data {
*/ */
struct mutex lock; struct mutex lock;
struct ads1015_channel_data channel_data[ADS1015_CHANNELS]; struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
unsigned int *data_rate;
}; };
static bool ads1015_is_writeable_reg(struct device *dev, unsigned int reg) static bool ads1015_is_writeable_reg(struct device *dev, unsigned int reg)
...@@ -157,6 +208,18 @@ static const struct iio_chan_spec ads1015_channels[] = { ...@@ -157,6 +208,18 @@ static const struct iio_chan_spec ads1015_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP), IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP),
}; };
static const struct iio_chan_spec ads1115_channels[] = {
ADS1115_V_DIFF_CHAN(0, 1, ADS1015_AIN0_AIN1),
ADS1115_V_DIFF_CHAN(0, 3, ADS1015_AIN0_AIN3),
ADS1115_V_DIFF_CHAN(1, 3, ADS1015_AIN1_AIN3),
ADS1115_V_DIFF_CHAN(2, 3, ADS1015_AIN2_AIN3),
ADS1115_V_CHAN(0, ADS1015_AIN0),
ADS1115_V_CHAN(1, ADS1015_AIN1),
ADS1115_V_CHAN(2, ADS1015_AIN2),
ADS1115_V_CHAN(3, ADS1015_AIN3),
IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP),
};
static int ads1015_set_power_state(struct ads1015_data *data, bool on) static int ads1015_set_power_state(struct ads1015_data *data, bool on)
{ {
int ret; int ret;
...@@ -196,7 +259,7 @@ int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val) ...@@ -196,7 +259,7 @@ int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val)
return ret; return ret;
if (change) { if (change) {
conv_time = DIV_ROUND_UP(USEC_PER_SEC, ads1015_data_rate[dr]); conv_time = DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr]);
usleep_range(conv_time, conv_time + 1); usleep_range(conv_time, conv_time + 1);
} }
...@@ -225,7 +288,8 @@ static irqreturn_t ads1015_trigger_handler(int irq, void *p) ...@@ -225,7 +288,8 @@ static irqreturn_t ads1015_trigger_handler(int irq, void *p)
buf[0] = res; buf[0] = res;
mutex_unlock(&data->lock); mutex_unlock(&data->lock);
iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); iio_push_to_buffers_with_timestamp(indio_dev, buf,
iio_get_time_ns(indio_dev));
err: err:
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
...@@ -263,7 +327,7 @@ static int ads1015_set_data_rate(struct ads1015_data *data, int chan, int rate) ...@@ -263,7 +327,7 @@ static int ads1015_set_data_rate(struct ads1015_data *data, int chan, int rate)
int i, ret, rindex = -1; int i, ret, rindex = -1;
for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++) for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++)
if (ads1015_data_rate[i] == rate) { if (data->data_rate[i] == rate) {
rindex = i; rindex = i;
break; break;
} }
...@@ -291,7 +355,9 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, ...@@ -291,7 +355,9 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
mutex_lock(&data->lock); mutex_lock(&data->lock);
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW: {
int shift = chan->scan_type.shift;
if (iio_buffer_enabled(indio_dev)) { if (iio_buffer_enabled(indio_dev)) {
ret = -EBUSY; ret = -EBUSY;
break; break;
...@@ -307,8 +373,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, ...@@ -307,8 +373,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
break; break;
} }
/* 12 bit res, D0 is bit 4 in conversion register */ *val = sign_extend32(*val >> shift, 15 - shift);
*val = sign_extend32(*val >> 4, 11);
ret = ads1015_set_power_state(data, false); ret = ads1015_set_power_state(data, false);
if (ret < 0) if (ret < 0)
...@@ -316,6 +381,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, ...@@ -316,6 +381,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
ret = IIO_VAL_INT; ret = IIO_VAL_INT;
break; break;
}
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
idx = data->channel_data[chan->address].pga; idx = data->channel_data[chan->address].pga;
*val = ads1015_scale[idx].scale; *val = ads1015_scale[idx].scale;
...@@ -324,7 +390,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, ...@@ -324,7 +390,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
break; break;
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
idx = data->channel_data[chan->address].data_rate; idx = data->channel_data[chan->address].data_rate;
*val = ads1015_data_rate[idx]; *val = data->data_rate[idx];
ret = IIO_VAL_INT; ret = IIO_VAL_INT;
break; break;
default: default:
...@@ -380,12 +446,15 @@ static const struct iio_buffer_setup_ops ads1015_buffer_setup_ops = { ...@@ -380,12 +446,15 @@ static const struct iio_buffer_setup_ops ads1015_buffer_setup_ops = {
}; };
static IIO_CONST_ATTR(scale_available, "3 2 1 0.5 0.25 0.125"); static IIO_CONST_ATTR(scale_available, "3 2 1 0.5 0.25 0.125");
static IIO_CONST_ATTR(sampling_frequency_available,
"128 250 490 920 1600 2400 3300"); static IIO_CONST_ATTR_NAMED(ads1015_sampling_frequency_available,
sampling_frequency_available, "128 250 490 920 1600 2400 3300");
static IIO_CONST_ATTR_NAMED(ads1115_sampling_frequency_available,
sampling_frequency_available, "8 16 32 64 128 250 475 860");
static struct attribute *ads1015_attributes[] = { static struct attribute *ads1015_attributes[] = {
&iio_const_attr_scale_available.dev_attr.attr, &iio_const_attr_scale_available.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr, &iio_const_attr_ads1015_sampling_frequency_available.dev_attr.attr,
NULL, NULL,
}; };
...@@ -393,11 +462,28 @@ static const struct attribute_group ads1015_attribute_group = { ...@@ -393,11 +462,28 @@ static const struct attribute_group ads1015_attribute_group = {
.attrs = ads1015_attributes, .attrs = ads1015_attributes,
}; };
static const struct iio_info ads1015_info = { static struct attribute *ads1115_attributes[] = {
&iio_const_attr_scale_available.dev_attr.attr,
&iio_const_attr_ads1115_sampling_frequency_available.dev_attr.attr,
NULL,
};
static const struct attribute_group ads1115_attribute_group = {
.attrs = ads1115_attributes,
};
static struct iio_info ads1015_info = {
.driver_module = THIS_MODULE,
.read_raw = ads1015_read_raw,
.write_raw = ads1015_write_raw,
.attrs = &ads1015_attribute_group,
};
static struct iio_info ads1115_info = {
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
.read_raw = ads1015_read_raw, .read_raw = ads1015_read_raw,
.write_raw = ads1015_write_raw, .write_raw = ads1015_write_raw,
.attrs = &ads1015_attribute_group, .attrs = &ads1115_attribute_group,
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF
...@@ -500,12 +586,25 @@ static int ads1015_probe(struct i2c_client *client, ...@@ -500,12 +586,25 @@ static int ads1015_probe(struct i2c_client *client,
mutex_init(&data->lock); mutex_init(&data->lock);
indio_dev->dev.parent = &client->dev; indio_dev->dev.parent = &client->dev;
indio_dev->info = &ads1015_info; indio_dev->dev.of_node = client->dev.of_node;
indio_dev->name = ADS1015_DRV_NAME; indio_dev->name = ADS1015_DRV_NAME;
indio_dev->channels = ads1015_channels;
indio_dev->num_channels = ARRAY_SIZE(ads1015_channels);
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
switch (id->driver_data) {
case ADS1015:
indio_dev->channels = ads1015_channels;
indio_dev->num_channels = ARRAY_SIZE(ads1015_channels);
indio_dev->info = &ads1015_info;
data->data_rate = (unsigned int *) &ads1015_data_rate;
break;
case ADS1115:
indio_dev->channels = ads1115_channels;
indio_dev->num_channels = ARRAY_SIZE(ads1115_channels);
indio_dev->info = &ads1115_info;
data->data_rate = (unsigned int *) &ads1115_data_rate;
break;
}
/* we need to keep this ABI the same as used by hwmon ADS1015 driver */ /* we need to keep this ABI the same as used by hwmon ADS1015 driver */
ads1015_get_channels_config(client); ads1015_get_channels_config(client);
...@@ -590,7 +689,8 @@ static const struct dev_pm_ops ads1015_pm_ops = { ...@@ -590,7 +689,8 @@ static const struct dev_pm_ops ads1015_pm_ops = {
}; };
static const struct i2c_device_id ads1015_id[] = { static const struct i2c_device_id ads1015_id[] = {
{"ads1015", 0}, {"ads1015", ADS1015},
{"ads1115", ADS1115},
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, ads1015_id); MODULE_DEVICE_TABLE(i2c, ads1015_id);
......
...@@ -421,6 +421,7 @@ static int ads8688_probe(struct spi_device *spi) ...@@ -421,6 +421,7 @@ static int ads8688_probe(struct spi_device *spi)
indio_dev->name = spi_get_device_id(spi)->name; indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->dev.of_node = spi->dev.of_node;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = st->chip_info->channels; indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels; indio_dev->num_channels = st->chip_info->num_channels;
......
...@@ -326,8 +326,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) ...@@ -326,8 +326,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
int i; int i;
indio_dev->num_channels = channels; indio_dev->num_channels = channels;
chan_array = kcalloc(channels, chan_array = kcalloc(channels, sizeof(*chan_array), GFP_KERNEL);
sizeof(struct iio_chan_spec), GFP_KERNEL);
if (chan_array == NULL) if (chan_array == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -467,8 +466,7 @@ static int tiadc_probe(struct platform_device *pdev) ...@@ -467,8 +466,7 @@ static int tiadc_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
indio_dev = devm_iio_device_alloc(&pdev->dev, indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*indio_dev));
sizeof(struct tiadc_device));
if (indio_dev == NULL) { if (indio_dev == NULL) {
dev_err(&pdev->dev, "failed to allocate iio device\n"); dev_err(&pdev->dev, "failed to allocate iio device\n");
return -ENOMEM; return -ENOMEM;
...@@ -531,8 +529,7 @@ static int tiadc_remove(struct platform_device *pdev) ...@@ -531,8 +529,7 @@ static int tiadc_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM static int __maybe_unused tiadc_suspend(struct device *dev)
static int tiadc_suspend(struct device *dev)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct tiadc_device *adc_dev = iio_priv(indio_dev); struct tiadc_device *adc_dev = iio_priv(indio_dev);
...@@ -550,7 +547,7 @@ static int tiadc_suspend(struct device *dev) ...@@ -550,7 +547,7 @@ static int tiadc_suspend(struct device *dev)
return 0; return 0;
} }
static int tiadc_resume(struct device *dev) static int __maybe_unused tiadc_resume(struct device *dev)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct tiadc_device *adc_dev = iio_priv(indio_dev); struct tiadc_device *adc_dev = iio_priv(indio_dev);
...@@ -567,14 +564,7 @@ static int tiadc_resume(struct device *dev) ...@@ -567,14 +564,7 @@ static int tiadc_resume(struct device *dev)
return 0; return 0;
} }
static const struct dev_pm_ops tiadc_pm_ops = { static SIMPLE_DEV_PM_OPS(tiadc_pm_ops, tiadc_suspend, tiadc_resume);
.suspend = tiadc_suspend,
.resume = tiadc_resume,
};
#define TIADC_PM_OPS (&tiadc_pm_ops)
#else
#define TIADC_PM_OPS NULL
#endif
static const struct of_device_id ti_adc_dt_ids[] = { static const struct of_device_id ti_adc_dt_ids[] = {
{ .compatible = "ti,am3359-adc", }, { .compatible = "ti,am3359-adc", },
...@@ -585,7 +575,7 @@ MODULE_DEVICE_TABLE(of, ti_adc_dt_ids); ...@@ -585,7 +575,7 @@ MODULE_DEVICE_TABLE(of, ti_adc_dt_ids);
static struct platform_driver tiadc_driver = { static struct platform_driver tiadc_driver = {
.driver = { .driver = {
.name = "TI-am335x-adc", .name = "TI-am335x-adc",
.pm = TIADC_PM_OPS, .pm = &tiadc_pm_ops,
.of_match_table = ti_adc_dt_ids, .of_match_table = ti_adc_dt_ids,
}, },
.probe = tiadc_probe, .probe = tiadc_probe,
......
...@@ -594,7 +594,8 @@ static irqreturn_t vf610_adc_isr(int irq, void *dev_id) ...@@ -594,7 +594,8 @@ static irqreturn_t vf610_adc_isr(int irq, void *dev_id)
if (iio_buffer_enabled(indio_dev)) { if (iio_buffer_enabled(indio_dev)) {
info->buffer[0] = info->value; info->buffer[0] = info->value;
iio_push_to_buffers_with_timestamp(indio_dev, iio_push_to_buffers_with_timestamp(indio_dev,
info->buffer, iio_get_time_ns()); info->buffer,
iio_get_time_ns(indio_dev));
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
} else } else
complete(&info->completion); complete(&info->completion);
......
...@@ -46,7 +46,7 @@ static void xadc_handle_event(struct iio_dev *indio_dev, unsigned int event) ...@@ -46,7 +46,7 @@ static void xadc_handle_event(struct iio_dev *indio_dev, unsigned int event)
iio_push_event(indio_dev, iio_push_event(indio_dev,
IIO_UNMOD_EVENT_CODE(chan->type, chan->channel, IIO_UNMOD_EVENT_CODE(chan->type, chan->channel,
IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
iio_get_time_ns()); iio_get_time_ns(indio_dev));
} else { } else {
/* /*
* For other channels we don't know whether it is a upper or * For other channels we don't know whether it is a upper or
...@@ -56,7 +56,7 @@ static void xadc_handle_event(struct iio_dev *indio_dev, unsigned int event) ...@@ -56,7 +56,7 @@ static void xadc_handle_event(struct iio_dev *indio_dev, unsigned int event)
iio_push_event(indio_dev, iio_push_event(indio_dev,
IIO_UNMOD_EVENT_CODE(chan->type, chan->channel, IIO_UNMOD_EVENT_CODE(chan->type, chan->channel,
IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER), IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER),
iio_get_time_ns()); iio_get_time_ns(indio_dev));
} }
} }
......
...@@ -305,7 +305,7 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer) ...@@ -305,7 +305,7 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer)
queue->fileio.active_block = NULL; queue->fileio.active_block = NULL;
spin_lock_irq(&queue->list_lock); spin_lock_irq(&queue->list_lock);
for (i = 0; i < 2; i++) { for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) {
block = queue->fileio.blocks[i]; block = queue->fileio.blocks[i];
/* If we can't re-use it free it */ /* If we can't re-use it free it */
...@@ -323,7 +323,7 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer) ...@@ -323,7 +323,7 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer)
INIT_LIST_HEAD(&queue->incoming); INIT_LIST_HEAD(&queue->incoming);
for (i = 0; i < 2; i++) { for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) {
if (queue->fileio.blocks[i]) { if (queue->fileio.blocks[i]) {
block = queue->fileio.blocks[i]; block = queue->fileio.blocks[i];
if (block->state == IIO_BLOCK_STATE_DEAD) { if (block->state == IIO_BLOCK_STATE_DEAD) {
......
...@@ -5,15 +5,17 @@ ...@@ -5,15 +5,17 @@
menu "Chemical Sensors" menu "Chemical Sensors"
config ATLAS_PH_SENSOR config ATLAS_PH_SENSOR
tristate "Atlas Scientific OEM pH-SM sensor" tristate "Atlas Scientific OEM SM sensors"
depends on I2C depends on I2C
select REGMAP_I2C select REGMAP_I2C
select IIO_BUFFER select IIO_BUFFER
select IIO_TRIGGERED_BUFFER select IIO_TRIGGERED_BUFFER
select IRQ_WORK select IRQ_WORK
help help
Say Y here to build I2C interface support for the Atlas Say Y here to build I2C interface support for the following
Scientific OEM pH-SM sensor. Atlas Scientific OEM SM sensors:
* pH SM sensor
* EC SM sensor
To compile this driver as module, choose M here: the To compile this driver as module, choose M here: the
module will be called atlas-ph-sensor. module will be called atlas-ph-sensor.
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/irq_work.h> #include <linux/irq_work.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/of_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
...@@ -43,29 +44,50 @@ ...@@ -43,29 +44,50 @@
#define ATLAS_REG_PWR_CONTROL 0x06 #define ATLAS_REG_PWR_CONTROL 0x06
#define ATLAS_REG_CALIB_STATUS 0x0d #define ATLAS_REG_PH_CALIB_STATUS 0x0d
#define ATLAS_REG_CALIB_STATUS_MASK 0x07 #define ATLAS_REG_PH_CALIB_STATUS_MASK 0x07
#define ATLAS_REG_CALIB_STATUS_LOW BIT(0) #define ATLAS_REG_PH_CALIB_STATUS_LOW BIT(0)
#define ATLAS_REG_CALIB_STATUS_MID BIT(1) #define ATLAS_REG_PH_CALIB_STATUS_MID BIT(1)
#define ATLAS_REG_CALIB_STATUS_HIGH BIT(2) #define ATLAS_REG_PH_CALIB_STATUS_HIGH BIT(2)
#define ATLAS_REG_TEMP_DATA 0x0e #define ATLAS_REG_EC_CALIB_STATUS 0x0f
#define ATLAS_REG_EC_CALIB_STATUS_MASK 0x0f
#define ATLAS_REG_EC_CALIB_STATUS_DRY BIT(0)
#define ATLAS_REG_EC_CALIB_STATUS_SINGLE BIT(1)
#define ATLAS_REG_EC_CALIB_STATUS_LOW BIT(2)
#define ATLAS_REG_EC_CALIB_STATUS_HIGH BIT(3)
#define ATLAS_REG_PH_TEMP_DATA 0x0e
#define ATLAS_REG_PH_DATA 0x16 #define ATLAS_REG_PH_DATA 0x16
#define ATLAS_REG_EC_PROBE 0x08
#define ATLAS_REG_EC_TEMP_DATA 0x10
#define ATLAS_REG_EC_DATA 0x18
#define ATLAS_REG_TDS_DATA 0x1c
#define ATLAS_REG_PSS_DATA 0x20
#define ATLAS_PH_INT_TIME_IN_US 450000 #define ATLAS_PH_INT_TIME_IN_US 450000
#define ATLAS_EC_INT_TIME_IN_US 650000
enum {
ATLAS_PH_SM,
ATLAS_EC_SM,
};
struct atlas_data { struct atlas_data {
struct i2c_client *client; struct i2c_client *client;
struct iio_trigger *trig; struct iio_trigger *trig;
struct atlas_device *chip;
struct regmap *regmap; struct regmap *regmap;
struct irq_work work; struct irq_work work;
__be32 buffer[4]; /* 32-bit pH data + 32-bit pad + 64-bit timestamp */ __be32 buffer[6]; /* 96-bit data + 32-bit pad + 64-bit timestamp */
}; };
static const struct regmap_range atlas_volatile_ranges[] = { static const struct regmap_range atlas_volatile_ranges[] = {
regmap_reg_range(ATLAS_REG_INT_CONTROL, ATLAS_REG_INT_CONTROL), regmap_reg_range(ATLAS_REG_INT_CONTROL, ATLAS_REG_INT_CONTROL),
regmap_reg_range(ATLAS_REG_PH_DATA, ATLAS_REG_PH_DATA + 4), regmap_reg_range(ATLAS_REG_PH_DATA, ATLAS_REG_PH_DATA + 4),
regmap_reg_range(ATLAS_REG_EC_DATA, ATLAS_REG_PSS_DATA + 4),
}; };
static const struct regmap_access_table atlas_volatile_table = { static const struct regmap_access_table atlas_volatile_table = {
...@@ -80,13 +102,14 @@ static const struct regmap_config atlas_regmap_config = { ...@@ -80,13 +102,14 @@ static const struct regmap_config atlas_regmap_config = {
.val_bits = 8, .val_bits = 8,
.volatile_table = &atlas_volatile_table, .volatile_table = &atlas_volatile_table,
.max_register = ATLAS_REG_PH_DATA + 4, .max_register = ATLAS_REG_PSS_DATA + 4,
.cache_type = REGCACHE_RBTREE, .cache_type = REGCACHE_RBTREE,
}; };
static const struct iio_chan_spec atlas_channels[] = { static const struct iio_chan_spec atlas_ph_channels[] = {
{ {
.type = IIO_PH, .type = IIO_PH,
.address = ATLAS_REG_PH_DATA,
.info_mask_separate = .info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
.scan_index = 0, .scan_index = 0,
...@@ -100,7 +123,7 @@ static const struct iio_chan_spec atlas_channels[] = { ...@@ -100,7 +123,7 @@ static const struct iio_chan_spec atlas_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(1), IIO_CHAN_SOFT_TIMESTAMP(1),
{ {
.type = IIO_TEMP, .type = IIO_TEMP,
.address = ATLAS_REG_TEMP_DATA, .address = ATLAS_REG_PH_TEMP_DATA,
.info_mask_separate = .info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
.output = 1, .output = 1,
...@@ -108,6 +131,142 @@ static const struct iio_chan_spec atlas_channels[] = { ...@@ -108,6 +131,142 @@ static const struct iio_chan_spec atlas_channels[] = {
}, },
}; };
#define ATLAS_EC_CHANNEL(_idx, _addr) \
{\
.type = IIO_CONCENTRATION, \
.indexed = 1, \
.channel = _idx, \
.address = _addr, \
.info_mask_separate = \
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), \
.scan_index = _idx + 1, \
.scan_type = { \
.sign = 'u', \
.realbits = 32, \
.storagebits = 32, \
.endianness = IIO_BE, \
}, \
}
static const struct iio_chan_spec atlas_ec_channels[] = {
{
.type = IIO_ELECTRICALCONDUCTIVITY,
.address = ATLAS_REG_EC_DATA,
.info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
.scan_index = 0,
.scan_type = {
.sign = 'u',
.realbits = 32,
.storagebits = 32,
.endianness = IIO_BE,
},
},
ATLAS_EC_CHANNEL(0, ATLAS_REG_TDS_DATA),
ATLAS_EC_CHANNEL(1, ATLAS_REG_PSS_DATA),
IIO_CHAN_SOFT_TIMESTAMP(3),
{
.type = IIO_TEMP,
.address = ATLAS_REG_EC_TEMP_DATA,
.info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
.output = 1,
.scan_index = -1
},
};
static int atlas_check_ph_calibration(struct atlas_data *data)
{
struct device *dev = &data->client->dev;
int ret;
unsigned int val;
ret = regmap_read(data->regmap, ATLAS_REG_PH_CALIB_STATUS, &val);
if (ret)
return ret;
if (!(val & ATLAS_REG_PH_CALIB_STATUS_MASK)) {
dev_warn(dev, "device has not been calibrated\n");
return 0;
}
if (!(val & ATLAS_REG_PH_CALIB_STATUS_LOW))
dev_warn(dev, "device missing low point calibration\n");
if (!(val & ATLAS_REG_PH_CALIB_STATUS_MID))
dev_warn(dev, "device missing mid point calibration\n");
if (!(val & ATLAS_REG_PH_CALIB_STATUS_HIGH))
dev_warn(dev, "device missing high point calibration\n");
return 0;
}
static int atlas_check_ec_calibration(struct atlas_data *data)
{
struct device *dev = &data->client->dev;
int ret;
unsigned int val;
ret = regmap_bulk_read(data->regmap, ATLAS_REG_EC_PROBE, &val, 2);
if (ret)
return ret;
dev_info(dev, "probe set to K = %d.%.2d", be16_to_cpu(val) / 100,
be16_to_cpu(val) % 100);
ret = regmap_read(data->regmap, ATLAS_REG_EC_CALIB_STATUS, &val);
if (ret)
return ret;
if (!(val & ATLAS_REG_EC_CALIB_STATUS_MASK)) {
dev_warn(dev, "device has not been calibrated\n");
return 0;
}
if (!(val & ATLAS_REG_EC_CALIB_STATUS_DRY))
dev_warn(dev, "device missing dry point calibration\n");
if (val & ATLAS_REG_EC_CALIB_STATUS_SINGLE) {
dev_warn(dev, "device using single point calibration\n");
} else {
if (!(val & ATLAS_REG_EC_CALIB_STATUS_LOW))
dev_warn(dev, "device missing low point calibration\n");
if (!(val & ATLAS_REG_EC_CALIB_STATUS_HIGH))
dev_warn(dev, "device missing high point calibration\n");
}
return 0;
}
struct atlas_device {
const struct iio_chan_spec *channels;
int num_channels;
int data_reg;
int (*calibration)(struct atlas_data *data);
int delay;
};
static struct atlas_device atlas_devices[] = {
[ATLAS_PH_SM] = {
.channels = atlas_ph_channels,
.num_channels = 3,
.data_reg = ATLAS_REG_PH_DATA,
.calibration = &atlas_check_ph_calibration,
.delay = ATLAS_PH_INT_TIME_IN_US,
},
[ATLAS_EC_SM] = {
.channels = atlas_ec_channels,
.num_channels = 5,
.data_reg = ATLAS_REG_EC_DATA,
.calibration = &atlas_check_ec_calibration,
.delay = ATLAS_EC_INT_TIME_IN_US,
},
};
static int atlas_set_powermode(struct atlas_data *data, int on) static int atlas_set_powermode(struct atlas_data *data, int on)
{ {
return regmap_write(data->regmap, ATLAS_REG_PWR_CONTROL, on); return regmap_write(data->regmap, ATLAS_REG_PWR_CONTROL, on);
...@@ -178,12 +337,13 @@ static irqreturn_t atlas_trigger_handler(int irq, void *private) ...@@ -178,12 +337,13 @@ static irqreturn_t atlas_trigger_handler(int irq, void *private)
struct atlas_data *data = iio_priv(indio_dev); struct atlas_data *data = iio_priv(indio_dev);
int ret; int ret;
ret = regmap_bulk_read(data->regmap, ATLAS_REG_PH_DATA, ret = regmap_bulk_read(data->regmap, data->chip->data_reg,
(u8 *) &data->buffer, sizeof(data->buffer[0])); (u8 *) &data->buffer,
sizeof(__be32) * (data->chip->num_channels - 2));
if (!ret) if (!ret)
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
iio_get_time_ns()); iio_get_time_ns(indio_dev));
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
...@@ -200,7 +360,7 @@ static irqreturn_t atlas_interrupt_handler(int irq, void *private) ...@@ -200,7 +360,7 @@ static irqreturn_t atlas_interrupt_handler(int irq, void *private)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int atlas_read_ph_measurement(struct atlas_data *data, __be32 *val) static int atlas_read_measurement(struct atlas_data *data, int reg, __be32 *val)
{ {
struct device *dev = &data->client->dev; struct device *dev = &data->client->dev;
int suspended = pm_runtime_suspended(dev); int suspended = pm_runtime_suspended(dev);
...@@ -213,11 +373,9 @@ static int atlas_read_ph_measurement(struct atlas_data *data, __be32 *val) ...@@ -213,11 +373,9 @@ static int atlas_read_ph_measurement(struct atlas_data *data, __be32 *val)
} }
if (suspended) if (suspended)
usleep_range(ATLAS_PH_INT_TIME_IN_US, usleep_range(data->chip->delay, data->chip->delay + 100000);
ATLAS_PH_INT_TIME_IN_US + 100000);
ret = regmap_bulk_read(data->regmap, ATLAS_REG_PH_DATA, ret = regmap_bulk_read(data->regmap, reg, (u8 *) val, sizeof(*val));
(u8 *) val, sizeof(*val));
pm_runtime_mark_last_busy(dev); pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev); pm_runtime_put_autosuspend(dev);
...@@ -242,12 +400,15 @@ static int atlas_read_raw(struct iio_dev *indio_dev, ...@@ -242,12 +400,15 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
(u8 *) &reg, sizeof(reg)); (u8 *) &reg, sizeof(reg));
break; break;
case IIO_PH: case IIO_PH:
case IIO_CONCENTRATION:
case IIO_ELECTRICALCONDUCTIVITY:
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev)) if (iio_buffer_enabled(indio_dev))
ret = -EBUSY; ret = -EBUSY;
else else
ret = atlas_read_ph_measurement(data, &reg); ret = atlas_read_measurement(data,
chan->address, &reg);
mutex_unlock(&indio_dev->mlock); mutex_unlock(&indio_dev->mlock);
break; break;
...@@ -271,6 +432,14 @@ static int atlas_read_raw(struct iio_dev *indio_dev, ...@@ -271,6 +432,14 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
*val = 1; /* 0.001 */ *val = 1; /* 0.001 */
*val2 = 1000; *val2 = 1000;
break; break;
case IIO_ELECTRICALCONDUCTIVITY:
*val = 1; /* 0.00001 */
*val = 100000;
break;
case IIO_CONCENTRATION:
*val = 0; /* 0.000000001 */
*val2 = 1000;
return IIO_VAL_INT_PLUS_NANO;
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -303,37 +472,26 @@ static const struct iio_info atlas_info = { ...@@ -303,37 +472,26 @@ static const struct iio_info atlas_info = {
.write_raw = atlas_write_raw, .write_raw = atlas_write_raw,
}; };
static int atlas_check_calibration(struct atlas_data *data) static const struct i2c_device_id atlas_id[] = {
{ { "atlas-ph-sm", ATLAS_PH_SM},
struct device *dev = &data->client->dev; { "atlas-ec-sm", ATLAS_EC_SM},
int ret; {}
unsigned int val; };
MODULE_DEVICE_TABLE(i2c, atlas_id);
ret = regmap_read(data->regmap, ATLAS_REG_CALIB_STATUS, &val);
if (ret)
return ret;
if (!(val & ATLAS_REG_CALIB_STATUS_MASK)) {
dev_warn(dev, "device has not been calibrated\n");
return 0;
}
if (!(val & ATLAS_REG_CALIB_STATUS_LOW))
dev_warn(dev, "device missing low point calibration\n");
if (!(val & ATLAS_REG_CALIB_STATUS_MID))
dev_warn(dev, "device missing mid point calibration\n");
if (!(val & ATLAS_REG_CALIB_STATUS_HIGH))
dev_warn(dev, "device missing high point calibration\n");
return 0; static const struct of_device_id atlas_dt_ids[] = {
{ .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, },
{ .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, },
{ }
}; };
MODULE_DEVICE_TABLE(of, atlas_dt_ids);
static int atlas_probe(struct i2c_client *client, static int atlas_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct atlas_data *data; struct atlas_data *data;
struct atlas_device *chip;
const struct of_device_id *of_id;
struct iio_trigger *trig; struct iio_trigger *trig;
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
int ret; int ret;
...@@ -342,10 +500,16 @@ static int atlas_probe(struct i2c_client *client, ...@@ -342,10 +500,16 @@ static int atlas_probe(struct i2c_client *client,
if (!indio_dev) if (!indio_dev)
return -ENOMEM; return -ENOMEM;
of_id = of_match_device(atlas_dt_ids, &client->dev);
if (!of_id)
chip = &atlas_devices[id->driver_data];
else
chip = &atlas_devices[(unsigned long)of_id->data];
indio_dev->info = &atlas_info; indio_dev->info = &atlas_info;
indio_dev->name = ATLAS_DRV_NAME; indio_dev->name = ATLAS_DRV_NAME;
indio_dev->channels = atlas_channels; indio_dev->channels = chip->channels;
indio_dev->num_channels = ARRAY_SIZE(atlas_channels); indio_dev->num_channels = chip->num_channels;
indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE; indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE;
indio_dev->dev.parent = &client->dev; indio_dev->dev.parent = &client->dev;
...@@ -358,6 +522,7 @@ static int atlas_probe(struct i2c_client *client, ...@@ -358,6 +522,7 @@ static int atlas_probe(struct i2c_client *client,
data = iio_priv(indio_dev); data = iio_priv(indio_dev);
data->client = client; data->client = client;
data->trig = trig; data->trig = trig;
data->chip = chip;
trig->dev.parent = indio_dev->dev.parent; trig->dev.parent = indio_dev->dev.parent;
trig->ops = &atlas_interrupt_trigger_ops; trig->ops = &atlas_interrupt_trigger_ops;
iio_trigger_set_drvdata(trig, indio_dev); iio_trigger_set_drvdata(trig, indio_dev);
...@@ -379,7 +544,7 @@ static int atlas_probe(struct i2c_client *client, ...@@ -379,7 +544,7 @@ static int atlas_probe(struct i2c_client *client,
return -EINVAL; return -EINVAL;
} }
ret = atlas_check_calibration(data); ret = chip->calibration(data);
if (ret) if (ret)
return ret; return ret;
...@@ -480,18 +645,6 @@ static const struct dev_pm_ops atlas_pm_ops = { ...@@ -480,18 +645,6 @@ static const struct dev_pm_ops atlas_pm_ops = {
atlas_runtime_resume, NULL) atlas_runtime_resume, NULL)
}; };
static const struct i2c_device_id atlas_id[] = {
{ "atlas-ph-sm", 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, atlas_id);
static const struct of_device_id atlas_dt_ids[] = {
{ .compatible = "atlas,ph-sm" },
{ }
};
MODULE_DEVICE_TABLE(of, atlas_dt_ids);
static struct i2c_driver atlas_driver = { static struct i2c_driver atlas_driver = {
.driver = { .driver = {
.name = ATLAS_DRV_NAME, .name = ATLAS_DRV_NAME,
......
...@@ -22,34 +22,32 @@ ...@@ -22,34 +22,32 @@
#include <linux/iio/common/st_sensors.h> #include <linux/iio/common/st_sensors.h>
int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
{ {
int i, len; int i;
int total = 0;
struct st_sensor_data *sdata = iio_priv(indio_dev); struct st_sensor_data *sdata = iio_priv(indio_dev);
unsigned int num_data_channels = sdata->num_data_channels; unsigned int num_data_channels = sdata->num_data_channels;
for (i = 0; i < num_data_channels; i++) { for_each_set_bit(i, indio_dev->active_scan_mask, num_data_channels) {
unsigned int bytes_to_read; const struct iio_chan_spec *channel = &indio_dev->channels[i];
unsigned int bytes_to_read = channel->scan_type.realbits >> 3;
if (test_bit(i, indio_dev->active_scan_mask)) { unsigned int storage_bytes =
bytes_to_read = indio_dev->channels[i].scan_type.storagebits >> 3; channel->scan_type.storagebits >> 3;
len = sdata->tf->read_multiple_byte(&sdata->tb,
sdata->dev, indio_dev->channels[i].address, buf = PTR_ALIGN(buf, storage_bytes);
bytes_to_read, if (sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
buf + total, sdata->multiread_bit); channel->address,
bytes_to_read, buf,
if (len < bytes_to_read) sdata->multiread_bit) <
return -EIO; bytes_to_read)
return -EIO;
/* Advance the buffer pointer */
total += len; /* Advance the buffer pointer */
} buf += storage_bytes;
} }
return total; return 0;
} }
EXPORT_SYMBOL(st_sensors_get_buffer_element);
irqreturn_t st_sensors_trigger_handler(int irq, void *p) irqreturn_t st_sensors_trigger_handler(int irq, void *p)
{ {
...@@ -59,11 +57,16 @@ irqreturn_t st_sensors_trigger_handler(int irq, void *p) ...@@ -59,11 +57,16 @@ irqreturn_t st_sensors_trigger_handler(int irq, void *p)
struct st_sensor_data *sdata = iio_priv(indio_dev); struct st_sensor_data *sdata = iio_priv(indio_dev);
s64 timestamp; s64 timestamp;
/* If we do timetamping here, do it before reading the values */ /*
* If we do timetamping here, do it before reading the values, because
* once we've read the values, new interrupts can occur (when using
* the hardware trigger) and the hw_timestamp may get updated.
* By storing it in a local variable first, we are safe.
*/
if (sdata->hw_irq_trigger) if (sdata->hw_irq_trigger)
timestamp = sdata->hw_timestamp; timestamp = sdata->hw_timestamp;
else else
timestamp = iio_get_time_ns(); timestamp = iio_get_time_ns(indio_dev);
len = st_sensors_get_buffer_element(indio_dev, sdata->buffer_data); len = st_sensors_get_buffer_element(indio_dev, sdata->buffer_data);
if (len < 0) if (len < 0)
......
...@@ -228,7 +228,7 @@ int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable) ...@@ -228,7 +228,7 @@ int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable)
} }
EXPORT_SYMBOL(st_sensors_set_axis_enable); EXPORT_SYMBOL(st_sensors_set_axis_enable);
void st_sensors_power_enable(struct iio_dev *indio_dev) int st_sensors_power_enable(struct iio_dev *indio_dev)
{ {
struct st_sensor_data *pdata = iio_priv(indio_dev); struct st_sensor_data *pdata = iio_priv(indio_dev);
int err; int err;
...@@ -237,18 +237,37 @@ void st_sensors_power_enable(struct iio_dev *indio_dev) ...@@ -237,18 +237,37 @@ void st_sensors_power_enable(struct iio_dev *indio_dev)
pdata->vdd = devm_regulator_get_optional(indio_dev->dev.parent, "vdd"); pdata->vdd = devm_regulator_get_optional(indio_dev->dev.parent, "vdd");
if (!IS_ERR(pdata->vdd)) { if (!IS_ERR(pdata->vdd)) {
err = regulator_enable(pdata->vdd); err = regulator_enable(pdata->vdd);
if (err != 0) if (err != 0) {
dev_warn(&indio_dev->dev, dev_warn(&indio_dev->dev,
"Failed to enable specified Vdd supply\n"); "Failed to enable specified Vdd supply\n");
return err;
}
} else {
err = PTR_ERR(pdata->vdd);
if (err != -ENODEV)
return err;
} }
pdata->vdd_io = devm_regulator_get_optional(indio_dev->dev.parent, "vddio"); pdata->vdd_io = devm_regulator_get_optional(indio_dev->dev.parent, "vddio");
if (!IS_ERR(pdata->vdd_io)) { if (!IS_ERR(pdata->vdd_io)) {
err = regulator_enable(pdata->vdd_io); err = regulator_enable(pdata->vdd_io);
if (err != 0) if (err != 0) {
dev_warn(&indio_dev->dev, dev_warn(&indio_dev->dev,
"Failed to enable specified Vdd_IO supply\n"); "Failed to enable specified Vdd_IO supply\n");
goto st_sensors_disable_vdd;
}
} else {
err = PTR_ERR(pdata->vdd_io);
if (err != -ENODEV)
goto st_sensors_disable_vdd;
} }
return 0;
st_sensors_disable_vdd:
if (!IS_ERR_OR_NULL(pdata->vdd))
regulator_disable(pdata->vdd);
return err;
} }
EXPORT_SYMBOL(st_sensors_power_enable); EXPORT_SYMBOL(st_sensors_power_enable);
...@@ -256,10 +275,10 @@ void st_sensors_power_disable(struct iio_dev *indio_dev) ...@@ -256,10 +275,10 @@ void st_sensors_power_disable(struct iio_dev *indio_dev)
{ {
struct st_sensor_data *pdata = iio_priv(indio_dev); struct st_sensor_data *pdata = iio_priv(indio_dev);
if (!IS_ERR(pdata->vdd)) if (!IS_ERR_OR_NULL(pdata->vdd))
regulator_disable(pdata->vdd); regulator_disable(pdata->vdd);
if (!IS_ERR(pdata->vdd_io)) if (!IS_ERR_OR_NULL(pdata->vdd_io))
regulator_disable(pdata->vdd_io); regulator_disable(pdata->vdd_io);
} }
EXPORT_SYMBOL(st_sensors_power_disable); EXPORT_SYMBOL(st_sensors_power_disable);
...@@ -471,7 +490,7 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev, ...@@ -471,7 +490,7 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
int err; int err;
u8 *outdata; u8 *outdata;
struct st_sensor_data *sdata = iio_priv(indio_dev); struct st_sensor_data *sdata = iio_priv(indio_dev);
unsigned int byte_for_channel = ch->scan_type.storagebits >> 3; unsigned int byte_for_channel = ch->scan_type.realbits >> 3;
outdata = kmalloc(byte_for_channel, GFP_KERNEL); outdata = kmalloc(byte_for_channel, GFP_KERNEL);
if (!outdata) if (!outdata)
...@@ -531,7 +550,7 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev, ...@@ -531,7 +550,7 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev,
int num_sensors_list, int num_sensors_list,
const struct st_sensor_settings *sensor_settings) const struct st_sensor_settings *sensor_settings)
{ {
int i, n, err; int i, n, err = 0;
u8 wai; u8 wai;
struct st_sensor_data *sdata = iio_priv(indio_dev); struct st_sensor_data *sdata = iio_priv(indio_dev);
...@@ -551,17 +570,21 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev, ...@@ -551,17 +570,21 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev,
return -ENODEV; return -ENODEV;
} }
err = sdata->tf->read_byte(&sdata->tb, sdata->dev, if (sensor_settings[i].wai_addr) {
sensor_settings[i].wai_addr, &wai); err = sdata->tf->read_byte(&sdata->tb, sdata->dev,
if (err < 0) { sensor_settings[i].wai_addr, &wai);
dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n"); if (err < 0) {
return err; dev_err(&indio_dev->dev,
} "failed to read Who-Am-I register.\n");
return err;
}
if (sensor_settings[i].wai != wai) { if (sensor_settings[i].wai != wai) {
dev_err(&indio_dev->dev, "%s: WhoAmI mismatch (0x%x).\n", dev_err(&indio_dev->dev,
indio_dev->name, wai); "%s: WhoAmI mismatch (0x%x).\n",
return -EINVAL; indio_dev->name, wai);
return -EINVAL;
}
} }
sdata->sensor_settings = sdata->sensor_settings =
......
...@@ -48,8 +48,8 @@ static int st_sensors_i2c_read_multiple_byte( ...@@ -48,8 +48,8 @@ static int st_sensors_i2c_read_multiple_byte(
if (multiread_bit) if (multiread_bit)
reg_addr |= ST_SENSORS_I2C_MULTIREAD; reg_addr |= ST_SENSORS_I2C_MULTIREAD;
return i2c_smbus_read_i2c_block_data(to_i2c_client(dev), return i2c_smbus_read_i2c_block_data_or_emulated(to_i2c_client(dev),
reg_addr, len, data); reg_addr, len, data);
} }
static int st_sensors_i2c_write_byte(struct st_sensor_transfer_buffer *tb, static int st_sensors_i2c_write_byte(struct st_sensor_transfer_buffer *tb,
......
...@@ -17,6 +17,50 @@ ...@@ -17,6 +17,50 @@
#include <linux/iio/common/st_sensors.h> #include <linux/iio/common/st_sensors.h>
#include "st_sensors_core.h" #include "st_sensors_core.h"
/**
* st_sensors_new_samples_available() - check if more samples came in
* returns:
* 0 - no new samples available
* 1 - new samples available
* negative - error or unknown
*/
static int st_sensors_new_samples_available(struct iio_dev *indio_dev,
struct st_sensor_data *sdata)
{
u8 status;
int ret;
/* How would I know if I can't check it? */
if (!sdata->sensor_settings->drdy_irq.addr_stat_drdy)
return -EINVAL;
/* No scan mask, no interrupt */
if (!indio_dev->active_scan_mask)
return 0;
ret = sdata->tf->read_byte(&sdata->tb, sdata->dev,
sdata->sensor_settings->drdy_irq.addr_stat_drdy,
&status);
if (ret < 0) {
dev_err(sdata->dev,
"error checking samples available\n");
return ret;
}
/*
* the lower bits of .active_scan_mask[0] is directly mapped
* to the channels on the sensor: either bit 0 for
* one-dimensional sensors, or e.g. x,y,z for accelerometers,
* gyroscopes or magnetometers. No sensor use more than 3
* channels, so cut the other status bits here.
*/
status &= 0x07;
if (status & (u8)indio_dev->active_scan_mask[0])
return 1;
return 0;
}
/** /**
* st_sensors_irq_handler() - top half of the IRQ-based triggers * st_sensors_irq_handler() - top half of the IRQ-based triggers
* @irq: irq number * @irq: irq number
...@@ -29,7 +73,7 @@ irqreturn_t st_sensors_irq_handler(int irq, void *p) ...@@ -29,7 +73,7 @@ irqreturn_t st_sensors_irq_handler(int irq, void *p)
struct st_sensor_data *sdata = iio_priv(indio_dev); struct st_sensor_data *sdata = iio_priv(indio_dev);
/* Get the time stamp as close in time as possible */ /* Get the time stamp as close in time as possible */
sdata->hw_timestamp = iio_get_time_ns(); sdata->hw_timestamp = iio_get_time_ns(indio_dev);
return IRQ_WAKE_THREAD; return IRQ_WAKE_THREAD;
} }
...@@ -43,44 +87,43 @@ irqreturn_t st_sensors_irq_thread(int irq, void *p) ...@@ -43,44 +87,43 @@ irqreturn_t st_sensors_irq_thread(int irq, void *p)
struct iio_trigger *trig = p; struct iio_trigger *trig = p;
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
struct st_sensor_data *sdata = iio_priv(indio_dev); struct st_sensor_data *sdata = iio_priv(indio_dev);
int ret;
/* /*
* If this trigger is backed by a hardware interrupt and we have a * If this trigger is backed by a hardware interrupt and we have a
* status register, check if this IRQ came from us * status register, check if this IRQ came from us. Notice that
* we will process also if st_sensors_new_samples_available()
* returns negative: if we can't check status, then poll
* unconditionally.
*/ */
if (sdata->sensor_settings->drdy_irq.addr_stat_drdy) { if (sdata->hw_irq_trigger &&
u8 status; st_sensors_new_samples_available(indio_dev, sdata)) {
iio_trigger_poll_chained(p);
ret = sdata->tf->read_byte(&sdata->tb, sdata->dev, } else {
sdata->sensor_settings->drdy_irq.addr_stat_drdy, dev_dbg(sdata->dev, "spurious IRQ\n");
&status); return IRQ_NONE;
if (ret < 0) { }
dev_err(sdata->dev, "could not read channel status\n");
goto out_poll;
}
/*
* the lower bits of .active_scan_mask[0] is directly mapped
* to the channels on the sensor: either bit 0 for
* one-dimensional sensors, or e.g. x,y,z for accelerometers,
* gyroscopes or magnetometers. No sensor use more than 3
* channels, so cut the other status bits here.
*/
status &= 0x07;
/* /*
* If this was not caused by any channels on this sensor, * If we have proper level IRQs the handler will be re-entered if
* return IRQ_NONE * the line is still active, so return here and come back in through
*/ * the top half if need be.
if (!indio_dev->active_scan_mask) */
return IRQ_NONE; if (!sdata->edge_irq)
if (!(status & (u8)indio_dev->active_scan_mask[0])) return IRQ_HANDLED;
return IRQ_NONE;
/*
* If we are using egde IRQs, new samples arrived while processing
* the IRQ and those may be missed unless we pick them here, so poll
* again. If the sensor delivery frequency is very high, this thread
* turns into a polled loop handler.
*/
while (sdata->hw_irq_trigger &&
st_sensors_new_samples_available(indio_dev, sdata)) {
dev_dbg(sdata->dev, "more samples came in during polling\n");
sdata->hw_timestamp = iio_get_time_ns(indio_dev);
iio_trigger_poll_chained(p);
} }
out_poll:
/* It's our IRQ: proceed to handle the register polling */
iio_trigger_poll_chained(p);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -107,13 +150,18 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, ...@@ -107,13 +150,18 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
* If the IRQ is triggered on falling edge, we need to mark the * If the IRQ is triggered on falling edge, we need to mark the
* interrupt as active low, if the hardware supports this. * interrupt as active low, if the hardware supports this.
*/ */
if (irq_trig == IRQF_TRIGGER_FALLING) { switch(irq_trig) {
case IRQF_TRIGGER_FALLING:
case IRQF_TRIGGER_LOW:
if (!sdata->sensor_settings->drdy_irq.addr_ihl) { if (!sdata->sensor_settings->drdy_irq.addr_ihl) {
dev_err(&indio_dev->dev, dev_err(&indio_dev->dev,
"falling edge specified for IRQ but hardware " "falling/low specified for IRQ "
"only support rising edge, will request " "but hardware only support rising/high: "
"rising edge\n"); "will request rising/high\n");
irq_trig = IRQF_TRIGGER_RISING; if (irq_trig == IRQF_TRIGGER_FALLING)
irq_trig = IRQF_TRIGGER_RISING;
if (irq_trig == IRQF_TRIGGER_LOW)
irq_trig = IRQF_TRIGGER_HIGH;
} else { } else {
/* Set up INT active low i.e. falling edge */ /* Set up INT active low i.e. falling edge */
err = st_sensors_write_data_with_mask(indio_dev, err = st_sensors_write_data_with_mask(indio_dev,
...@@ -122,20 +170,39 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, ...@@ -122,20 +170,39 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
if (err < 0) if (err < 0)
goto iio_trigger_free; goto iio_trigger_free;
dev_info(&indio_dev->dev, dev_info(&indio_dev->dev,
"interrupts on the falling edge\n"); "interrupts on the falling edge or "
"active low level\n");
} }
} else if (irq_trig == IRQF_TRIGGER_RISING) { break;
case IRQF_TRIGGER_RISING:
dev_info(&indio_dev->dev, dev_info(&indio_dev->dev,
"interrupts on the rising edge\n"); "interrupts on the rising edge\n");
break;
} else { case IRQF_TRIGGER_HIGH:
dev_info(&indio_dev->dev,
"interrupts active high level\n");
break;
default:
/* This is the most preferred mode, if possible */
dev_err(&indio_dev->dev, dev_err(&indio_dev->dev,
"unsupported IRQ trigger specified (%lx), only " "unsupported IRQ trigger specified (%lx), enforce "
"rising and falling edges supported, enforce "
"rising edge\n", irq_trig); "rising edge\n", irq_trig);
irq_trig = IRQF_TRIGGER_RISING; irq_trig = IRQF_TRIGGER_RISING;
} }
/* Tell the interrupt handler that we're dealing with edges */
if (irq_trig == IRQF_TRIGGER_FALLING ||
irq_trig == IRQF_TRIGGER_RISING)
sdata->edge_irq = true;
else
/*
* If we're not using edges (i.e. level interrupts) we
* just mask off the IRQ, handle one interrupt, then
* if the line is still low, we return to the
* interrupt handler top half again and start over.
*/
irq_trig |= IRQF_ONESHOT;
/* /*
* If the interrupt pin is Open Drain, by definition this * If the interrupt pin is Open Drain, by definition this
* means that the interrupt line may be shared with other * means that the interrupt line may be shared with other
...@@ -148,9 +215,6 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, ...@@ -148,9 +215,6 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
sdata->sensor_settings->drdy_irq.addr_stat_drdy) sdata->sensor_settings->drdy_irq.addr_stat_drdy)
irq_trig |= IRQF_SHARED; irq_trig |= IRQF_SHARED;
/* Let's create an interrupt thread masking the hard IRQ here */
irq_trig |= IRQF_ONESHOT;
err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev), err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev),
st_sensors_irq_handler, st_sensors_irq_handler,
st_sensors_irq_thread, st_sensors_irq_thread,
......
...@@ -248,11 +248,12 @@ config MCP4922 ...@@ -248,11 +248,12 @@ config MCP4922
config STX104 config STX104
tristate "Apex Embedded Systems STX104 DAC driver" tristate "Apex Embedded Systems STX104 DAC driver"
depends on X86 && ISA_BUS_API depends on X86 && ISA_BUS_API
select GPIOLIB
help help
Say yes here to build support for the 2-channel DAC on the Apex Say yes here to build support for the 2-channel DAC and GPIO on the
Embedded Systems STX104 integrated analog PC/104 card. The base port Apex Embedded Systems STX104 integrated analog PC/104 card. The base
addresses for the devices may be configured via the "base" module port addresses for the devices may be configured via the base array
parameter array. module parameter.
config VF610_DAC config VF610_DAC
tristate "Vybrid vf610 DAC driver" tristate "Vybrid vf610 DAC driver"
......
...@@ -242,7 +242,7 @@ static irqreturn_t ad5421_fault_handler(int irq, void *data) ...@@ -242,7 +242,7 @@ static irqreturn_t ad5421_fault_handler(int irq, void *data)
0, 0,
IIO_EV_TYPE_THRESH, IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING), IIO_EV_DIR_RISING),
iio_get_time_ns()); iio_get_time_ns(indio_dev));
} }
if (events & AD5421_FAULT_UNDER_CURRENT) { if (events & AD5421_FAULT_UNDER_CURRENT) {
...@@ -251,7 +251,7 @@ static irqreturn_t ad5421_fault_handler(int irq, void *data) ...@@ -251,7 +251,7 @@ static irqreturn_t ad5421_fault_handler(int irq, void *data)
0, 0,
IIO_EV_TYPE_THRESH, IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING), IIO_EV_DIR_FALLING),
iio_get_time_ns()); iio_get_time_ns(indio_dev));
} }
if (events & AD5421_FAULT_TEMP_OVER_140) { if (events & AD5421_FAULT_TEMP_OVER_140) {
...@@ -260,7 +260,7 @@ static irqreturn_t ad5421_fault_handler(int irq, void *data) ...@@ -260,7 +260,7 @@ static irqreturn_t ad5421_fault_handler(int irq, void *data)
0, 0,
IIO_EV_TYPE_MAG, IIO_EV_TYPE_MAG,
IIO_EV_DIR_RISING), IIO_EV_DIR_RISING),
iio_get_time_ns()); iio_get_time_ns(indio_dev));
} }
old_fault = fault; old_fault = fault;
......
...@@ -223,7 +223,7 @@ static irqreturn_t ad5504_event_handler(int irq, void *private) ...@@ -223,7 +223,7 @@ static irqreturn_t ad5504_event_handler(int irq, void *private)
0, 0,
IIO_EV_TYPE_THRESH, IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING), IIO_EV_DIR_RISING),
iio_get_time_ns()); iio_get_time_ns((struct iio_dev *)private));
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/of.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
#include <linux/platform_data/ad5755.h> #include <linux/platform_data/ad5755.h>
...@@ -109,6 +110,51 @@ enum ad5755_type { ...@@ -109,6 +110,51 @@ enum ad5755_type {
ID_AD5737, ID_AD5737,
}; };
#ifdef CONFIG_OF
static const int ad5755_dcdc_freq_table[][2] = {
{ 250000, AD5755_DC_DC_FREQ_250kHZ },
{ 410000, AD5755_DC_DC_FREQ_410kHZ },
{ 650000, AD5755_DC_DC_FREQ_650kHZ }
};
static const int ad5755_dcdc_maxv_table[][2] = {
{ 23000000, AD5755_DC_DC_MAXV_23V },
{ 24500000, AD5755_DC_DC_MAXV_24V5 },
{ 27000000, AD5755_DC_DC_MAXV_27V },
{ 29500000, AD5755_DC_DC_MAXV_29V5 },
};
static const int ad5755_slew_rate_table[][2] = {
{ 64000, AD5755_SLEW_RATE_64k },
{ 32000, AD5755_SLEW_RATE_32k },
{ 16000, AD5755_SLEW_RATE_16k },
{ 8000, AD5755_SLEW_RATE_8k },
{ 4000, AD5755_SLEW_RATE_4k },
{ 2000, AD5755_SLEW_RATE_2k },
{ 1000, AD5755_SLEW_RATE_1k },
{ 500, AD5755_SLEW_RATE_500 },
{ 250, AD5755_SLEW_RATE_250 },
{ 125, AD5755_SLEW_RATE_125 },
{ 64, AD5755_SLEW_RATE_64 },
{ 32, AD5755_SLEW_RATE_32 },
{ 16, AD5755_SLEW_RATE_16 },
{ 8, AD5755_SLEW_RATE_8 },
{ 4, AD5755_SLEW_RATE_4 },
{ 0, AD5755_SLEW_RATE_0_5 },
};
static const int ad5755_slew_step_table[][2] = {
{ 256, AD5755_SLEW_STEP_SIZE_256 },
{ 128, AD5755_SLEW_STEP_SIZE_128 },
{ 64, AD5755_SLEW_STEP_SIZE_64 },
{ 32, AD5755_SLEW_STEP_SIZE_32 },
{ 16, AD5755_SLEW_STEP_SIZE_16 },
{ 4, AD5755_SLEW_STEP_SIZE_4 },
{ 2, AD5755_SLEW_STEP_SIZE_2 },
{ 1, AD5755_SLEW_STEP_SIZE_1 },
};
#endif
static int ad5755_write_unlocked(struct iio_dev *indio_dev, static int ad5755_write_unlocked(struct iio_dev *indio_dev,
unsigned int reg, unsigned int val) unsigned int reg, unsigned int val)
{ {
...@@ -556,6 +602,129 @@ static const struct ad5755_platform_data ad5755_default_pdata = { ...@@ -556,6 +602,129 @@ static const struct ad5755_platform_data ad5755_default_pdata = {
}, },
}; };
#ifdef CONFIG_OF
static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
{
struct device_node *np = dev->of_node;
struct device_node *pp;
struct ad5755_platform_data *pdata;
unsigned int tmp;
unsigned int tmparray[3];
int devnr, i;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return NULL;
pdata->ext_dc_dc_compenstation_resistor =
of_property_read_bool(np, "adi,ext-dc-dc-compenstation-resistor");
if (!of_property_read_u32(np, "adi,dc-dc-phase", &tmp))
pdata->dc_dc_phase = tmp;
else
pdata->dc_dc_phase = AD5755_DC_DC_PHASE_ALL_SAME_EDGE;
pdata->dc_dc_freq = AD5755_DC_DC_FREQ_410kHZ;
if (!of_property_read_u32(np, "adi,dc-dc-freq-hz", &tmp)) {
for (i = 0; i < ARRAY_SIZE(ad5755_dcdc_freq_table); i++) {
if (tmp == ad5755_dcdc_freq_table[i][0]) {
pdata->dc_dc_freq = ad5755_dcdc_freq_table[i][1];
break;
}
}
if (i == ARRAY_SIZE(ad5755_dcdc_freq_table)) {
dev_err(dev,
"adi,dc-dc-freq out of range selecting 410kHz");
}
}
pdata->dc_dc_maxv = AD5755_DC_DC_MAXV_23V;
if (!of_property_read_u32(np, "adi,dc-dc-max-microvolt", &tmp)) {
for (i = 0; i < ARRAY_SIZE(ad5755_dcdc_maxv_table); i++) {
if (tmp == ad5755_dcdc_maxv_table[i][0]) {
pdata->dc_dc_maxv = ad5755_dcdc_maxv_table[i][1];
break;
}
}
if (i == ARRAY_SIZE(ad5755_dcdc_maxv_table)) {
dev_err(dev,
"adi,dc-dc-maxv out of range selecting 23V");
}
}
devnr = 0;
for_each_child_of_node(np, pp) {
if (devnr > AD5755_NUM_CHANNELS) {
dev_err(dev,
"There is to many channels defined in DT\n");
goto error_out;
}
if (!of_property_read_u32(pp, "adi,mode", &tmp))
pdata->dac[devnr].mode = tmp;
else
pdata->dac[devnr].mode = AD5755_MODE_CURRENT_4mA_20mA;
pdata->dac[devnr].ext_current_sense_resistor =
of_property_read_bool(pp, "adi,ext-current-sense-resistor");
pdata->dac[devnr].enable_voltage_overrange =
of_property_read_bool(pp, "adi,enable-voltage-overrange");
if (!of_property_read_u32_array(pp, "adi,slew", tmparray, 3)) {
pdata->dac[devnr].slew.enable = tmparray[0];
pdata->dac[devnr].slew.rate = AD5755_SLEW_RATE_64k;
for (i = 0; i < ARRAY_SIZE(ad5755_slew_rate_table); i++) {
if (tmparray[1] == ad5755_slew_rate_table[i][0]) {
pdata->dac[devnr].slew.rate =
ad5755_slew_rate_table[i][1];
break;
}
}
if (i == ARRAY_SIZE(ad5755_slew_rate_table)) {
dev_err(dev,
"channel %d slew rate out of range selecting 64kHz",
devnr);
}
pdata->dac[devnr].slew.step_size = AD5755_SLEW_STEP_SIZE_1;
for (i = 0; i < ARRAY_SIZE(ad5755_slew_step_table); i++) {
if (tmparray[2] == ad5755_slew_step_table[i][0]) {
pdata->dac[devnr].slew.step_size =
ad5755_slew_step_table[i][1];
break;
}
}
if (i == ARRAY_SIZE(ad5755_slew_step_table)) {
dev_err(dev,
"channel %d slew step size out of range selecting 1 LSB",
devnr);
}
} else {
pdata->dac[devnr].slew.enable = false;
pdata->dac[devnr].slew.rate = AD5755_SLEW_RATE_64k;
pdata->dac[devnr].slew.step_size =
AD5755_SLEW_STEP_SIZE_1;
}
devnr++;
}
return pdata;
error_out:
devm_kfree(dev, pdata);
return NULL;
}
#else
static
struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
{
return NULL;
}
#endif
static int ad5755_probe(struct spi_device *spi) static int ad5755_probe(struct spi_device *spi)
{ {
enum ad5755_type type = spi_get_device_id(spi)->driver_data; enum ad5755_type type = spi_get_device_id(spi)->driver_data;
...@@ -583,8 +752,15 @@ static int ad5755_probe(struct spi_device *spi) ...@@ -583,8 +752,15 @@ static int ad5755_probe(struct spi_device *spi)
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->num_channels = AD5755_NUM_CHANNELS; indio_dev->num_channels = AD5755_NUM_CHANNELS;
if (!pdata) if (spi->dev.of_node)
pdata = ad5755_parse_dt(&spi->dev);
else
pdata = spi->dev.platform_data;
if (!pdata) {
dev_warn(&spi->dev, "no platform data? using default\n");
pdata = &ad5755_default_pdata; pdata = &ad5755_default_pdata;
}
ret = ad5755_init_channels(indio_dev, pdata); ret = ad5755_init_channels(indio_dev, pdata);
if (ret) if (ret)
...@@ -607,6 +783,16 @@ static const struct spi_device_id ad5755_id[] = { ...@@ -607,6 +783,16 @@ static const struct spi_device_id ad5755_id[] = {
}; };
MODULE_DEVICE_TABLE(spi, ad5755_id); MODULE_DEVICE_TABLE(spi, ad5755_id);
static const struct of_device_id ad5755_of_match[] = {
{ .compatible = "adi,ad5755" },
{ .compatible = "adi,ad5755-1" },
{ .compatible = "adi,ad5757" },
{ .compatible = "adi,ad5735" },
{ .compatible = "adi,ad5737" },
{ }
};
MODULE_DEVICE_TABLE(of, ad5755_of_match);
static struct spi_driver ad5755_driver = { static struct spi_driver ad5755_driver = {
.driver = { .driver = {
.name = "ad5755", .name = "ad5755",
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/gpio/driver.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/types.h> #include <linux/iio/types.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -21,6 +22,7 @@ ...@@ -21,6 +22,7 @@
#include <linux/isa.h> #include <linux/isa.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/spinlock.h>
#define STX104_NUM_CHAN 2 #define STX104_NUM_CHAN 2
...@@ -49,6 +51,20 @@ struct stx104_iio { ...@@ -49,6 +51,20 @@ struct stx104_iio {
unsigned base; unsigned base;
}; };
/**
* struct stx104_gpio - GPIO device private data structure
* @chip: instance of the gpio_chip
* @lock: synchronization lock to prevent I/O race conditions
* @base: base port address of the GPIO device
* @out_state: output bits state
*/
struct stx104_gpio {
struct gpio_chip chip;
spinlock_t lock;
unsigned int base;
unsigned int out_state;
};
static int stx104_read_raw(struct iio_dev *indio_dev, static int stx104_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long mask) struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{ {
...@@ -88,15 +104,81 @@ static const struct iio_chan_spec stx104_channels[STX104_NUM_CHAN] = { ...@@ -88,15 +104,81 @@ static const struct iio_chan_spec stx104_channels[STX104_NUM_CHAN] = {
STX104_CHAN(1) STX104_CHAN(1)
}; };
static int stx104_gpio_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
if (offset < 4)
return 1;
return 0;
}
static int stx104_gpio_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
if (offset >= 4)
return -EINVAL;
return 0;
}
static int stx104_gpio_direction_output(struct gpio_chip *chip,
unsigned int offset, int value)
{
if (offset < 4)
return -EINVAL;
chip->set(chip, offset, value);
return 0;
}
static int stx104_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
if (offset >= 4)
return -EINVAL;
return !!(inb(stx104gpio->base) & BIT(offset));
}
static void stx104_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
const unsigned int mask = BIT(offset) >> 4;
unsigned long flags;
if (offset < 4)
return;
spin_lock_irqsave(&stx104gpio->lock, flags);
if (value)
stx104gpio->out_state |= mask;
else
stx104gpio->out_state &= ~mask;
outb(stx104gpio->out_state, stx104gpio->base);
spin_unlock_irqrestore(&stx104gpio->lock, flags);
}
static int stx104_probe(struct device *dev, unsigned int id) static int stx104_probe(struct device *dev, unsigned int id)
{ {
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct stx104_iio *priv; struct stx104_iio *priv;
struct stx104_gpio *stx104gpio;
int err;
indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
if (!indio_dev) if (!indio_dev)
return -ENOMEM; return -ENOMEM;
stx104gpio = devm_kzalloc(dev, sizeof(*stx104gpio), GFP_KERNEL);
if (!stx104gpio)
return -ENOMEM;
if (!devm_request_region(dev, base[id], STX104_EXTENT, if (!devm_request_region(dev, base[id], STX104_EXTENT,
dev_name(dev))) { dev_name(dev))) {
dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
...@@ -117,14 +199,53 @@ static int stx104_probe(struct device *dev, unsigned int id) ...@@ -117,14 +199,53 @@ static int stx104_probe(struct device *dev, unsigned int id)
outw(0, base[id] + 4); outw(0, base[id] + 4);
outw(0, base[id] + 6); outw(0, base[id] + 6);
return devm_iio_device_register(dev, indio_dev); err = devm_iio_device_register(dev, indio_dev);
if (err) {
dev_err(dev, "IIO device registering failed (%d)\n", err);
return err;
}
stx104gpio->chip.label = dev_name(dev);
stx104gpio->chip.parent = dev;
stx104gpio->chip.owner = THIS_MODULE;
stx104gpio->chip.base = -1;
stx104gpio->chip.ngpio = 8;
stx104gpio->chip.get_direction = stx104_gpio_get_direction;
stx104gpio->chip.direction_input = stx104_gpio_direction_input;
stx104gpio->chip.direction_output = stx104_gpio_direction_output;
stx104gpio->chip.get = stx104_gpio_get;
stx104gpio->chip.set = stx104_gpio_set;
stx104gpio->base = base[id] + 3;
stx104gpio->out_state = 0x0;
spin_lock_init(&stx104gpio->lock);
dev_set_drvdata(dev, stx104gpio);
err = gpiochip_add_data(&stx104gpio->chip, stx104gpio);
if (err) {
dev_err(dev, "GPIO registering failed (%d)\n", err);
return err;
}
return 0;
}
static int stx104_remove(struct device *dev, unsigned int id)
{
struct stx104_gpio *const stx104gpio = dev_get_drvdata(dev);
gpiochip_remove(&stx104gpio->chip);
return 0;
} }
static struct isa_driver stx104_driver = { static struct isa_driver stx104_driver = {
.probe = stx104_probe, .probe = stx104_probe,
.driver = { .driver = {
.name = "stx104" .name = "stx104"
} },
.remove = stx104_remove
}; };
module_isa_driver(stx104_driver, num_stx104); module_isa_driver(stx104_driver, num_stx104);
......
...@@ -10,6 +10,7 @@ config IIO_DUMMY_EVGEN ...@@ -10,6 +10,7 @@ config IIO_DUMMY_EVGEN
config IIO_SIMPLE_DUMMY config IIO_SIMPLE_DUMMY
tristate "An example driver with no hardware requirements" tristate "An example driver with no hardware requirements"
depends on IIO_SW_DEVICE
help help
Driver intended mainly as documentation for how to write Driver intended mainly as documentation for how to write
a driver. May also be useful for testing userspace code a driver. May also be useful for testing userspace code
......
...@@ -17,26 +17,18 @@ ...@@ -17,26 +17,18 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/string.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
#include <linux/iio/events.h> #include <linux/iio/events.h>
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/iio/sw_device.h>
#include "iio_simple_dummy.h" #include "iio_simple_dummy.h"
/* static struct config_item_type iio_dummy_type = {
* A few elements needed to fake a bus for this driver .ct_owner = THIS_MODULE,
* Note instances parameter controls how many of these };
* dummy devices are registered.
*/
static unsigned instances = 1;
module_param(instances, uint, 0);
/* Pointer array used to fake bus elements */
static struct iio_dev **iio_dummy_devs;
/* Fake a name for the part number, usually obtained from the id table */
static const char *iio_dummy_part_number = "iio_dummy_part_no";
/** /**
* struct iio_dummy_accel_calibscale - realworld to register mapping * struct iio_dummy_accel_calibscale - realworld to register mapping
...@@ -572,12 +564,18 @@ static int iio_dummy_init_device(struct iio_dev *indio_dev) ...@@ -572,12 +564,18 @@ static int iio_dummy_init_device(struct iio_dev *indio_dev)
* const struct i2c_device_id *id) * const struct i2c_device_id *id)
* SPI: iio_dummy_probe(struct spi_device *spi) * SPI: iio_dummy_probe(struct spi_device *spi)
*/ */
static int iio_dummy_probe(int index) static struct iio_sw_device *iio_dummy_probe(const char *name)
{ {
int ret; int ret;
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct iio_dummy_state *st; struct iio_dummy_state *st;
struct iio_sw_device *swd;
swd = kzalloc(sizeof(*swd), GFP_KERNEL);
if (!swd) {
ret = -ENOMEM;
goto error_kzalloc;
}
/* /*
* Allocate an IIO device. * Allocate an IIO device.
* *
...@@ -608,7 +606,7 @@ static int iio_dummy_probe(int index) ...@@ -608,7 +606,7 @@ static int iio_dummy_probe(int index)
* i2c_set_clientdata(client, indio_dev); * i2c_set_clientdata(client, indio_dev);
* spi_set_drvdata(spi, indio_dev); * spi_set_drvdata(spi, indio_dev);
*/ */
iio_dummy_devs[index] = indio_dev; swd->device = indio_dev;
/* /*
* Set the device name. * Set the device name.
...@@ -619,7 +617,7 @@ static int iio_dummy_probe(int index) ...@@ -619,7 +617,7 @@ static int iio_dummy_probe(int index)
* indio_dev->name = id->name; * indio_dev->name = id->name;
* indio_dev->name = spi_get_device_id(spi)->name; * indio_dev->name = spi_get_device_id(spi)->name;
*/ */
indio_dev->name = iio_dummy_part_number; indio_dev->name = kstrdup(name, GFP_KERNEL);
/* Provide description of available channels */ /* Provide description of available channels */
indio_dev->channels = iio_dummy_channels; indio_dev->channels = iio_dummy_channels;
...@@ -646,7 +644,9 @@ static int iio_dummy_probe(int index) ...@@ -646,7 +644,9 @@ static int iio_dummy_probe(int index)
if (ret < 0) if (ret < 0)
goto error_unconfigure_buffer; goto error_unconfigure_buffer;
return 0; iio_swd_group_init_type_name(swd, name, &iio_dummy_type);
return swd;
error_unconfigure_buffer: error_unconfigure_buffer:
iio_simple_dummy_unconfigure_buffer(indio_dev); iio_simple_dummy_unconfigure_buffer(indio_dev);
error_unregister_events: error_unregister_events:
...@@ -654,16 +654,18 @@ static int iio_dummy_probe(int index) ...@@ -654,16 +654,18 @@ static int iio_dummy_probe(int index)
error_free_device: error_free_device:
iio_device_free(indio_dev); iio_device_free(indio_dev);
error_ret: error_ret:
return ret; kfree(swd);
error_kzalloc:
return ERR_PTR(ret);
} }
/** /**
* iio_dummy_remove() - device instance removal function * iio_dummy_remove() - device instance removal function
* @index: device index. * @swd: pointer to software IIO device abstraction
* *
* Parameters follow those of iio_dummy_probe for buses. * Parameters follow those of iio_dummy_probe for buses.
*/ */
static void iio_dummy_remove(int index) static int iio_dummy_remove(struct iio_sw_device *swd)
{ {
/* /*
* Get a pointer to the device instance iio_dev structure * Get a pointer to the device instance iio_dev structure
...@@ -671,7 +673,7 @@ static void iio_dummy_remove(int index) ...@@ -671,7 +673,7 @@ static void iio_dummy_remove(int index)
* struct iio_dev *indio_dev = i2c_get_clientdata(client); * struct iio_dev *indio_dev = i2c_get_clientdata(client);
* struct iio_dev *indio_dev = spi_get_drvdata(spi); * struct iio_dev *indio_dev = spi_get_drvdata(spi);
*/ */
struct iio_dev *indio_dev = iio_dummy_devs[index]; struct iio_dev *indio_dev = swd->device;
/* Unregister the device */ /* Unregister the device */
iio_device_unregister(indio_dev); iio_device_unregister(indio_dev);
...@@ -684,11 +686,13 @@ static void iio_dummy_remove(int index) ...@@ -684,11 +686,13 @@ static void iio_dummy_remove(int index)
iio_simple_dummy_events_unregister(indio_dev); iio_simple_dummy_events_unregister(indio_dev);
/* Free all structures */ /* Free all structures */
kfree(indio_dev->name);
iio_device_free(indio_dev); iio_device_free(indio_dev);
}
return 0;
}
/** /**
* iio_dummy_init() - device driver registration * module_iio_sw_device_driver() - device driver registration
* *
* Varies depending on bus type of the device. As there is no device * Varies depending on bus type of the device. As there is no device
* here, call probe directly. For information on device registration * here, call probe directly. For information on device registration
...@@ -697,50 +701,18 @@ static void iio_dummy_remove(int index) ...@@ -697,50 +701,18 @@ static void iio_dummy_remove(int index)
* spi: * spi:
* Documentation/spi/spi-summary * Documentation/spi/spi-summary
*/ */
static __init int iio_dummy_init(void) static const struct iio_sw_device_ops iio_dummy_device_ops = {
{ .probe = iio_dummy_probe,
int i, ret; .remove = iio_dummy_remove,
};
if (instances > 10) {
instances = 1;
return -EINVAL;
}
/* Fake a bus */
iio_dummy_devs = kcalloc(instances, sizeof(*iio_dummy_devs),
GFP_KERNEL);
/* Here we have no actual device so call probe */
for (i = 0; i < instances; i++) {
ret = iio_dummy_probe(i);
if (ret < 0)
goto error_remove_devs;
}
return 0;
error_remove_devs:
while (i--)
iio_dummy_remove(i);
kfree(iio_dummy_devs);
return ret;
}
module_init(iio_dummy_init);
/** static struct iio_sw_device_type iio_dummy_device = {
* iio_dummy_exit() - device driver removal .name = "dummy",
* .owner = THIS_MODULE,
* Varies depending on bus type of the device. .ops = &iio_dummy_device_ops,
* As there is no device here, call remove directly. };
*/
static __exit void iio_dummy_exit(void)
{
int i;
for (i = 0; i < instances; i++) module_iio_sw_device_driver(iio_dummy_device);
iio_dummy_remove(i);
kfree(iio_dummy_devs);
}
module_exit(iio_dummy_exit);
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
MODULE_DESCRIPTION("IIO dummy driver"); MODULE_DESCRIPTION("IIO dummy driver");
......
...@@ -85,7 +85,8 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) ...@@ -85,7 +85,8 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
} }
} }
iio_push_to_buffers_with_timestamp(indio_dev, data, iio_get_time_ns()); iio_push_to_buffers_with_timestamp(indio_dev, data,
iio_get_time_ns(indio_dev));
kfree(data); kfree(data);
......
...@@ -158,7 +158,7 @@ static irqreturn_t iio_simple_dummy_get_timestamp(int irq, void *private) ...@@ -158,7 +158,7 @@ static irqreturn_t iio_simple_dummy_get_timestamp(int irq, void *private)
struct iio_dev *indio_dev = private; struct iio_dev *indio_dev = private;
struct iio_dummy_state *st = iio_priv(indio_dev); struct iio_dummy_state *st = iio_priv(indio_dev);
st->event_timestamp = iio_get_time_ns(); st->event_timestamp = iio_get_time_ns(indio_dev);
return IRQ_WAKE_THREAD; return IRQ_WAKE_THREAD;
} }
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -276,6 +276,7 @@ static const struct i2c_device_id am2315_i2c_id[] = { ...@@ -276,6 +276,7 @@ static const struct i2c_device_id am2315_i2c_id[] = {
{"am2315", 0}, {"am2315", 0},
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, am2315_i2c_id);
static const struct acpi_device_id am2315_acpi_id[] = { static const struct acpi_device_id am2315_acpi_id[] = {
{"AOS2315", 0}, {"AOS2315", 0},
......
...@@ -236,6 +236,7 @@ static const struct i2c_device_id htu21_id[] = { ...@@ -236,6 +236,7 @@ static const struct i2c_device_id htu21_id[] = {
{"ms8607-humidity", MS8607}, {"ms8607-humidity", MS8607},
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, htu21_id);
static struct i2c_driver htu21_driver = { static struct i2c_driver htu21_driver = {
.probe = htu21_probe, .probe = htu21_probe,
......
...@@ -79,4 +79,7 @@ void iio_device_unregister_eventset(struct iio_dev *indio_dev); ...@@ -79,4 +79,7 @@ void iio_device_unregister_eventset(struct iio_dev *indio_dev);
void iio_device_wakeup_eventset(struct iio_dev *indio_dev); void iio_device_wakeup_eventset(struct iio_dev *indio_dev);
int iio_event_getfd(struct iio_dev *indio_dev); int iio_event_getfd(struct iio_dev *indio_dev);
struct iio_event_interface;
bool iio_event_enabled(const struct iio_event_interface *ev_int);
#endif #endif
此差异已折叠。
...@@ -170,6 +170,7 @@ static const struct i2c_device_id inv_mpu_id[] = { ...@@ -170,6 +170,7 @@ static const struct i2c_device_id inv_mpu_id[] = {
{"mpu6050", INV_MPU6050}, {"mpu6050", INV_MPU6050},
{"mpu6500", INV_MPU6500}, {"mpu6500", INV_MPU6500},
{"mpu9150", INV_MPU9150}, {"mpu9150", INV_MPU9150},
{"icm20608", INV_ICM20608},
{} {}
}; };
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册