Commit c6a677c6 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull staging/IIO updates from Greg KH:
 "Here is the big staging tree update for 4.12-rc1.

  It's a big one, adding about 350k new lines of crap^Wcode, mostly all
  in a big dump of media drivers from Intel. But there's other new
  drivers in here as well, yet-another-wifi driver, new IIO drivers, and
  a new crypto accelerator.

  We also deleted a bunch of stuff, mostly in patch cleanups, but also
  the Android ION code has shrunk a lot, and the Android low memory
  killer driver was finally deleted, much to the celebration of the -mm
  developers.

  All of these have been in linux-next with a few build issues that will
  show up when you merge to your tree"

Merge conflicts in the new rtl8723bs driver (due to the wifi changes
this merge window) handled as per linux-next, courtesy of Stephen
Rothwell.

* tag 'staging-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (1182 commits)
  staging: fsl-mc/dpio: add cpu <--> LE conversion for dpaa2_fd
  staging: ks7010: remove line continuations in quoted strings
  staging: vt6656: use tabs instead of spaces
  staging: android: ion: Fix unnecessary initialization of static variable
  staging: media: atomisp: fix range checking on clk_num
  staging: media: atomisp: fix misspelled word in comment
  staging: media: atomisp: kmap() can't fail
  staging: atomisp: remove #ifdef for runtime PM functions
  staging: atomisp: satm include directory is gone
  atomisp: remove some more unused files
  atomisp: remove hmm_load/store/clear indirections
  atomisp: kill off mmgr_free
  atomisp: clean up the hmm init/cleanup indirections
  atomisp: handle allocation calls before init in the hmm layer
  staging: fsl-dpaa2/eth: Add maintainer for Ethernet driver
  staging: fsl-dpaa2/eth: Add TODO file
  staging: fsl-dpaa2/eth: Add trace points
  staging: fsl-dpaa2/eth: Add driver specific stats
  staging: fsl-dpaa2/eth: Add ethtool support
  staging: fsl-dpaa2/eth: Add Freescale DPAA2 Ethernet driver
  ...
parents e87d51ac 11270059

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

......@@ -111,6 +111,7 @@ Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@osg.samsung.com>
Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@s-opensource.com>
Matt Ranostay <mranostay@gmail.com> Matthew Ranostay <mranostay@embeddedalley.com>
Matt Ranostay <mranostay@gmail.com> <matt.ranostay@intel.com>
Matt Ranostay <matt.ranostay@konsulko.com> <matt@ranostay.consulting>
Mayuresh Janorkar <mayur@ti.com>
Michael Buesch <m@bues.ch>
Michel Dänzer <michel@tungstengraphics.com>
......
......@@ -55,6 +55,7 @@ Description:
then it is to be found in the base device directory.
What: /sys/bus/iio/devices/iio:deviceX/sampling_frequency_available
What: /sys/bus/iio/devices/iio:deviceX/in_proximity_sampling_frequency_available
What: /sys/.../iio:deviceX/buffer/sampling_frequency_available
What: /sys/bus/iio/devices/triggerX/sampling_frequency_available
KernelVersion: 2.6.35
......@@ -1593,7 +1594,7 @@ Description:
can be processed to siemens per meter.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_raw
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Raw counter device counts from channel Y. For quadrature
......@@ -1601,10 +1602,24 @@ Description:
the counts of a single quadrature signal phase from channel Y.
What: /sys/bus/iio/devices/iio:deviceX/in_indexY_raw
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Raw counter device index value from channel Y. This attribute
provides an absolute positional reference (e.g. a pulse once per
revolution) which may be used to home positional systems as
required.
What: /sys/bus/iio/devices/iio:deviceX/in_count_count_direction_available
KernelVersion: 4.12
Contact: linux-iio@vger.kernel.org
Description:
A list of possible counting directions which are:
- "up" : counter device is increasing.
- "down": counter device is decreasing.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_direction
KernelVersion: 4.12
Contact: linux-iio@vger.kernel.org
Description:
Raw counter device counters direction for channel Y.
What: /sys/bus/iio/devices/iio:deviceX/in_power_shunt_resistor
Date: March 2017
KernelVersion: 4.12
Contact: linux-iio@vger.kernel.org
Description: The value of the shunt resistor used to compute power drain on
common input voltage pin (RS+). In Ohms.
What: /sys/bus/iio/devices/iio:deviceX/in_current_shunt_resistor
Date: March 2017
KernelVersion: 4.12
Contact: linux-iio@vger.kernel.org
Description: The value of the shunt resistor used to compute current flowing
between RS+ and RS- voltage sense inputs. In Ohms.
These attributes describe a single physical component, exposed as two distinct
attributes as it is used to calculate two different values: power load and
current flowing between RS+ and RS- inputs.
What: /sys/bus/iio/devices/iio:deviceX/in_count_count_direction_available
What: /sys/bus/iio/devices/iio:deviceX/in_count_count_mode_available
What: /sys/bus/iio/devices/iio:deviceX/in_count_noise_error_available
What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available
What: /sys/bus/iio/devices/iio:deviceX/in_index_index_polarity_available
What: /sys/bus/iio/devices/iio:deviceX/in_index_synchronous_mode_available
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Discrete set of available values for the respective counter
configuration are listed in this file.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_direction
KernelVersion: 4.9
Contact: linux-iio@vger.kernel.org
Description:
Read-only attribute that indicates whether the counter for
channel Y is counting up or down.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_mode
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Count mode for channel Y. Four count modes are available:
......@@ -52,7 +44,7 @@ Description:
continuously throughout.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_noise_error
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Read-only attribute that indicates whether excessive noise is
......@@ -60,14 +52,14 @@ Description:
irrelevant in non-quadrature clock mode.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_preset
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
If the counter device supports preset registers, the preset
count for channel Y is provided by this attribute.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_quadrature_mode
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Configure channel Y counter for non-quadrature or quadrature
......@@ -88,7 +80,7 @@ Description:
decoded for UP/DN clock.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_set_to_preset_on_index
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Whether to set channel Y counter with channel Y preset value
......@@ -96,14 +88,14 @@ Description:
Valid attribute values are boolean.
What: /sys/bus/iio/devices/iio:deviceX/in_indexY_index_polarity
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Active level of channel Y index input; irrelevant in
non-synchronous load mode.
What: /sys/bus/iio/devices/iio:deviceX/in_indexY_synchronous_mode
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Configure channel Y counter for non-synchronous or synchronous
......
......@@ -3,11 +3,15 @@ KernelVersion: 4.11
Contact: benjamin.gaignard@st.com
Description:
Reading returns the list possible master modes which are:
- "reset" : The UG bit from the TIMx_EGR register is used as trigger output (TRGO).
- "enable" : The Counter Enable signal CNT_EN is used as trigger output.
- "reset" : The UG bit from the TIMx_EGR register is
used as trigger output (TRGO).
- "enable" : The Counter Enable signal CNT_EN is used
as trigger output.
- "update" : The update event is selected as trigger output.
For instance a master timer can then be used as a prescaler for a slave timer.
- "compare_pulse" : The trigger output send a positive pulse when the CC1IF flag is to be set.
For instance a master timer can then be used
as a prescaler for a slave timer.
- "compare_pulse" : The trigger output send a positive pulse
when the CC1IF flag is to be set.
- "OC1REF" : OC1REF signal is used as trigger output.
- "OC2REF" : OC2REF signal is used as trigger output.
- "OC3REF" : OC3REF signal is used as trigger output.
......@@ -27,3 +31,62 @@ Description:
Reading returns the current sampling frequency.
Writing an value different of 0 set and start sampling.
Writing 0 stop sampling.
What: /sys/bus/iio/devices/iio:deviceX/in_count0_preset
KernelVersion: 4.12
Contact: benjamin.gaignard@st.com
Description:
Reading returns the current preset value.
Writing sets the preset value.
When counting up the counter starts from 0 and fires an
event when reach preset value.
When counting down the counter start from preset value
and fire event when reach 0.
What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available
KernelVersion: 4.12
Contact: benjamin.gaignard@st.com
Description:
Reading returns the list possible quadrature modes.
What: /sys/bus/iio/devices/iio:deviceX/in_count0_quadrature_mode
KernelVersion: 4.12
Contact: benjamin.gaignard@st.com
Description:
Configure the device counter quadrature modes:
channel_A:
Encoder A input servers as the count input and B as
the UP/DOWN direction control input.
channel_B:
Encoder B input serves as the count input and A as
the UP/DOWN direction control input.
quadrature:
Encoder A and B inputs are mixed to get direction
and count with a scale of 0.25.
What: /sys/bus/iio/devices/iio:deviceX/in_count_enable_mode_available
KernelVersion: 4.12
Contact: benjamin.gaignard@st.com
Description:
Reading returns the list possible enable modes.
What: /sys/bus/iio/devices/iio:deviceX/in_count0_enable_mode
KernelVersion: 4.12
Contact: benjamin.gaignard@st.com
Description:
Configure the device counter enable modes, in all case
counting direction is set by in_count0_count_direction
attribute and the counter is clocked by the internal clock.
always:
Counter is always ON.
gated:
Counting is enabled when connected trigger signal
level is high else counting is disabled.
triggered:
Counting is enabled on rising edge of the connected
trigger, and remains enabled for the duration of this
selected mode.
Analog Devices ADXL345 3-Axis, +/-(2g/4g/8g/16g) Digital Accelerometer
http://www.analog.com/en/products/mems/accelerometers/adxl345.html
Required properties:
- compatible : should be "adi,adxl345"
- reg : the I2C address or SPI chip select number of the sensor
Required properties for SPI bus usage:
- spi-max-frequency : set maximum clock frequency, must be 5000000
- spi-cpol and spi-cpha : must be defined for adxl345 to enable SPI mode 3
Optional properties:
- interrupt-parent : phandle to the parent interrupt controller as documented
in Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
- interrupts: interrupt mapping for IRQ as documented in
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
Example for a I2C device node:
accelerometer@2a {
compatible = "adi,adxl345";
reg = <0x53>;
interrupt-parent = <&gpio1>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
};
Example for a SPI device node:
accelerometer@0 {
compatible = "adi,adxl345";
reg = <0>;
spi-max-frequency = <5000000>;
spi-cpol;
spi-cpha;
interrupt-parent = <&gpio1>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
};
......@@ -7,6 +7,7 @@ Required properties:
- "amlogic,meson-gxm-saradc" for GXM
along with the generic "amlogic,meson-saradc"
- reg: the physical base address and length of the registers
- interrupts: the interrupt indicating end of sampling
- clocks: phandle and clock identifier (see clock-names)
- clock-names: mandatory clocks:
- "clkin" for the reference clock (typically XTAL)
......@@ -23,6 +24,7 @@ Example:
compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc";
#io-channel-cells = <1>;
reg = <0x0 0x8680 0x0 0x34>;
interrupts = <GIC_SPI 73 IRQ_TYPE_EDGE_RISING>;
clocks = <&xtal>,
<&clkc CLKID_SAR_ADC>,
<&clkc CLKID_SANA>,
......
Aspeed ADC
This device is a 10-bit converter for 16 voltage channels. All inputs are
single ended.
Required properties:
- compatible: Should be "aspeed,ast2400-adc" or "aspeed,ast2500-adc"
- reg: memory window mapping address and length
- clocks: Input clock used to derive the sample clock. Expected to be the
SoC's APB clock.
- #io-channel-cells: Must be set to <1> to indicate channels are selected
by index.
Example:
adc@1e6e9000 {
compatible = "aspeed,ast2400-adc";
reg = <0x1e6e9000 0xb0>;
clocks = <&clk_apb>;
#io-channel-cells = <1>;
};
Motorola CPCAP PMIC ADC binding
Required properties:
- compatible: Should be "motorola,cpcap-adc" or "motorola,mapphone-cpcap-adc"
- interrupt-parent: The interrupt controller
- interrupts: The interrupt number for the ADC device
- interrupt-names: Should be "adcdone"
- #io-channel-cells: Number of cells in an IIO specifier
Example:
cpcap_adc: adc {
compatible = "motorola,mapphone-cpcap-adc";
interrupt-parent = <&cpcap>;
interrupts = <8 IRQ_TYPE_NONE>;
interrupt-names = "adcdone";
#io-channel-cells = <1>;
};
* Linear Technology / Analog Devices LTC2497 ADC
Required properties:
- compatible: Must be "lltc,ltc2497"
- reg: Must contain the ADC I2C address
- vref-supply: The regulator supply for ADC reference voltage
Example:
ltc2497: adc@76 {
compatible = "lltc,ltc2497";
reg = <0x76>;
vref-supply = <&ltc2497_reg>;
};
* MAX1117/MAX1118/MAX1119 8-bit, dual-channel ADCs
Required properties:
- compatible: Should be one of
* "maxim,max1117"
* "maxim,max1118"
* "maxim,max1119"
- reg: spi chip select number for the device
- (max1118 only) vref-supply: The regulator supply for ADC reference voltage
Recommended properties:
- spi-max-frequency: Definition as per
Documentation/devicetree/bindings/spi/spi-bus.txt
Example:
adc@0 {
compatible = "maxim,max1118";
reg = <0>;
vref-supply = <&vdd_supply>;
spi-max-frequency = <1000000>;
};
* Maxim max9611/max9612 current sense amplifier with 12-bits ADC interface
Maxim max9611/max9612 is an high-side current sense amplifier with integrated
12-bits ADC communicating over I2c bus.
The device node for this driver shall be a child of a I2c controller.
Required properties
- compatible: Should be "maxim,max9611" or "maxim,max9612"
- reg: The 7-bits long I2c address of the device
- shunt-resistor-micro-ohms: Value, in micro Ohms, of the current sense shunt
resistor
Example:
&i2c4 {
csa: adc@7c {
compatible = "maxim,max9611";
reg = <0x7c>;
shunt-resistor-micro-ohms = <5000>;
};
};
This device node describes a current sense amplifier sitting on I2c4 bus
with address 0x7c (read address is 0xf9, write address is 0xf8).
A sense resistor of 0,005 Ohm is installed between RS+ and RS- current-sensing
inputs.
......@@ -19,32 +19,42 @@ Required properties:
with PMIC variant but is typically something like 2.2 or 1.8V.
The following required properties are standard for IO channels, see
iio-bindings.txt for more details:
iio-bindings.txt for more details, but notice that this particular
ADC has a special addressing scheme that require two cells for
identifying each ADC channel:
- #address-cells: should be set to <1>
- #address-cells: should be set to <2>, the first cell is the
prescaler (on PM8058) or premux (on PM8921) with two valid bits
so legal values are 0x00, 0x01 or 0x02. The second cell
is the main analog mux setting (0x00..0x0f). The combination
of prescaler/premux and analog mux uniquely addresses a hardware
channel on all systems.
- #size-cells: should be set to <0>
- #io-channel-cells: should be set to <1>
- #io-channel-cells: should be set to <2>, again the cells are
precaler or premux followed by the analog muxing line.
- interrupts: should refer to the parent PMIC interrupt controller
and reference the proper ADC interrupt.
Required subnodes:
The ADC channels are configured as subnodes of the ADC. Since some of
them are used for calibrating the ADC, these nodes are compulsory:
The ADC channels are configured as subnodes of the ADC.
Since some of them are used for calibrating the ADC, these nodes are
compulsory:
adc-channel@c {
reg = <0x0c>;
reg = <0x00 0x0c>;
};
adc-channel@d {
reg = <0x0d>;
reg = <0x00 0x0d>;
};
adc-channel@f {
reg = <0x0f>;
reg = <0x00 0x0f>;
};
These three nodes are used for absolute and ratiometric calibration
......@@ -52,13 +62,13 @@ and only need to have these reg values: they are by hardware definition
1:1 ratio converters that sample 625, 1250 and 0 milliV and create
an interpolation calibration for all other ADCs.
Optional subnodes: any channels other than channel 0x0c, 0x0d and
0x0f are optional.
Optional subnodes: any channels other than channels [0x00 0x0c],
[0x00 0x0d] and [0x00 0x0f] are optional.
Required channel node properties:
- reg: should contain the hardware channel number in the range
0 .. 0x0f (4 bits). The hardware only supports 16 channels.
0 .. 0xff (8 bits).
Optional channel node properties:
......@@ -94,56 +104,54 @@ Example:
xoadc: xoadc@197 {
compatible = "qcom,pm8058-adc";
reg = <0x197>;
interrupt-parent = <&pm8058>;
interrupts = <76 1>;
#address-cells = <1>;
interrupts-extended = <&pm8058 76 IRQ_TYPE_EDGE_RISING>;
#address-cells = <2>;
#size-cells = <0>;
#io-channel-cells = <1>;
#io-channel-cells = <2>;
vcoin: adc-channel@0 {
reg = <0x00>;
reg = <0x00 0x00>;
};
vbat: adc-channel@1 {
reg = <0x01>;
reg = <0x00 0x01>;
};
dcin: adc-channel@2 {
reg = <0x02>;
reg = <0x00 0x02>;
};
ichg: adc-channel@3 {
reg = <0x03>;
reg = <0x00 0x03>;
};
vph_pwr: adc-channel@4 {
reg = <0x04>;
reg = <0x00 0x04>;
};
usb_vbus: adc-channel@a {
reg = <0x0a>;
reg = <0x00 0x0a>;
};
die_temp: adc-channel@b {
reg = <0x0b>;
reg = <0x00 0x0b>;
};
ref_625mv: adc-channel@c {
reg = <0x0c>;
reg = <0x00 0x0c>;
};
ref_1250mv: adc-channel@d {
reg = <0x0d>;
reg = <0x00 0x0d>;
};
ref_325mv: adc-channel@e {
reg = <0x0e>;
reg = <0x00 0x0e>;
};
ref_muxoff: adc-channel@f {
reg = <0x0f>;
reg = <0x00 0x0f>;
};
};
/* IIO client node */
iio-hwmon {
compatible = "iio-hwmon";
io-channels = <&xoadc 0x01>, /* Battery */
<&xoadc 0x02>, /* DC in (charger) */
<&xoadc 0x04>, /* VPH the main system voltage */
<&xoadc 0x0b>, /* Die temperature */
<&xoadc 0x0c>, /* Reference voltage 1.25V */
<&xoadc 0x0d>, /* Reference voltage 0.625V */
<&xoadc 0x0e>; /* Reference voltage 0.325V */
io-channels = <&xoadc 0x00 0x01>, /* Battery */
<&xoadc 0x00 0x02>, /* DC in (charger) */
<&xoadc 0x00 0x04>, /* VPH the main system voltage */
<&xoadc 0x00 0x0b>, /* Die temperature */
<&xoadc 0x00 0x0c>, /* Reference voltage 1.25V */
<&xoadc 0x00 0x0d>, /* Reference voltage 0.625V */
<&xoadc 0x00 0x0e>; /* Reference voltage 0.325V */
};
......@@ -4,6 +4,7 @@ Required properties:
- compatible: should be "rockchip,<name>-saradc" or "rockchip,rk3066-tsadc"
- "rockchip,saradc": for rk3188, rk3288
- "rockchip,rk3066-tsadc": for rk3036
- "rockchip,rk3328-saradc", "rockchip,rk3399-saradc": for rk3328
- "rockchip,rk3399-saradc": for rk3399
- reg: physical base address of the controller and length of memory mapped
......
......@@ -57,6 +57,9 @@ Optional properties:
- dmas: Phandle to dma channel for this ADC instance.
See ../../dma/dma.txt for details.
- dma-names: Must be "rx" when dmas property is being used.
- assigned-resolution-bits: Resolution (bits) to use for conversions. Must
match device available resolutions (e.g. can be 6, 8, 10 or 12 on stm32f4).
Default is maximum resolution if unset.
Example:
adc: adc@40012000 {
......@@ -84,6 +87,7 @@ Example:
st,adc-channels = <8>;
dmas = <&dma2 0 0 0x400 0x0>;
dma-names = "rx";
assigned-resolution-bits = <8>;
};
...
other adc child nodes follow...
......
Linear Technology LTC2632 DAC device driver
Required properties:
- compatible: Has to contain one of the following:
lltc,ltc2632-l12
lltc,ltc2632-l10
lltc,ltc2632-l8
lltc,ltc2632-h12
lltc,ltc2632-h10
lltc,ltc2632-h8
Property rules described in Documentation/devicetree/bindings/spi/spi-bus.txt
apply. In particular, "reg" and "spi-max-frequency" properties must be given.
Example:
spi_master {
dac: ltc2632@0 {
compatible = "lltc,ltc2632-l12";
reg = <0>; /* CS0 */
spi-max-frequency = <1000000>;
};
};
STMicroelectronics STM32 DAC
The STM32 DAC is a 12-bit voltage output digital-to-analog converter. The DAC
may be configured in 8 or 12-bit mode. It has two output channels, each with
its own converter.
It has built-in noise and triangle waveform generator and supports external
triggers for conversions. The DAC's output buffer allows a high drive output
current.
Contents of a stm32 dac root node:
-----------------------------------
Required properties:
- compatible: Must be "st,stm32h7-dac-core".
- reg: Offset and length of the device's register set.
- clocks: Must contain an entry for pclk (which feeds the peripheral bus
interface)
- clock-names: Must be "pclk".
- vref-supply: Phandle to the vref+ input analog reference supply.
- #address-cells = <1>;
- #size-cells = <0>;
Optional properties:
- resets: Must contain the phandle to the reset controller.
- A pinctrl state named "default" for each DAC channel may be defined to set
DAC_OUTx pin in mode of operation for analog output on external pin.
Contents of a stm32 dac child node:
-----------------------------------
DAC core node should contain at least one subnode, representing a
DAC instance/channel available on the machine.
Required properties:
- compatible: Must be "st,stm32-dac".
- reg: Must be either 1 or 2, to define (single) channel in use
- #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in
Documentation/devicetree/bindings/iio/iio-bindings.txt
Example:
dac: dac@40007400 {
compatible = "st,stm32h7-dac-core";
reg = <0x40007400 0x400>;
clocks = <&clk>;
clock-names = "pclk";
vref-supply = <&reg_vref>;
pinctrl-names = "default";
pinctrl-0 = <&dac_out1 &dac_out2>;
#address-cells = <1>;
#size-cells = <0>;
dac1: dac@1 {
compatible = "st,stm32-dac";
#io-channels-cells = <1>;
reg = <1>;
};
dac2: dac@2 {
compatible = "st,stm32-dac";
#io-channels-cells = <1>;
reg = <2>;
};
};
Maxim MAX30102 heart rate and pulse oximeter sensor
* https://datasheets.maximintegrated.com/en/ds/MAX30102.pdf
Required properties:
- compatible: must be "maxim,max30102"
- 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.
Optional properties:
- maxim,red-led-current-microamp: configuration for RED LED current
- maxim,ir-led-current-microamp: configuration for IR LED current
Note that each step is approximately 200 microamps, ranging from 0 uA to
50800 uA.
Example:
max30100@57 {
compatible = "maxim,max30102";
reg = <0x57>;
maxim,red-led-current-microamp = <7000>;
maxim,ir-led-current-microamp = <7000>;
interrupt-parent = <&gpio1>;
interrupts = <16 2>;
};
......@@ -3,14 +3,21 @@ InvenSense MPU-6050 Six-Axis (Gyro + Accelerometer) MEMS MotionTracking Device
http://www.invensense.com/mems/gyro/mpu6050.html
Required properties:
- compatible : should be "invensense,mpu6050"
- compatible : should be one of
"invensense,mpu6050"
"invensense,mpu6500"
"invensense,mpu9150"
"invensense,mpu9250"
"invensense,icm20608"
- reg : the I2C address of the sensor
- interrupt-parent : should be the phandle for the interrupt controller
- interrupts : interrupt mapping for GPIO IRQ
Optional properties:
- mount-matrix: an optional 3x3 mounting rotation matrix
- i2c-gate node. These devices also support an auxiliary i2c bus. This is
simple enough to be described using the i2c-gate binding. See
i2c/i2c-gate.txt for more details.
Example:
mpu6050@68 {
......@@ -28,3 +35,19 @@ Example:
"0", /* y2 */
"0.984807753012208"; /* z2 */
};
mpu9250@68 {
compatible = "invensense,mpu9250";
reg = <0x68>;
interrupt-parent = <&gpio3>;
interrupts = <21 1>;
i2c-gate {
#address-cells = <1>;
#size-cells = <0>;
ax8975@c {
compatible = "ak,ak8975";
reg = <0x0c>;
};
};
};
......@@ -3,6 +3,8 @@
Required properties:
- compatible: must be one of:
"st,lsm6ds3"
"st,lsm6ds3h"
"st,lsm6dsl"
"st,lsm6dsm"
- reg: i2c address of the sensor / spi cs line
......
STMicro VL6180 - ALS, range and proximity sensor
Link to datasheet: http://www.st.com/resource/en/datasheet/vl6180x.pdf
Required properties:
-compatible: should be "st,vl6180"
-reg: the I2C address of the sensor
Example:
vl6180@29 {
compatible = "st,vl6180";
reg = <0x29>;
};
* Devantech SRF04 ultrasonic range finder
Bit-banging driver using two GPIOs
Required properties:
- compatible: Should be "devantech,srf04"
- trig-gpios: Definition of the GPIO for the triggering (output)
This GPIO is set for about 10 us by the driver to tell the
device it should initiate the measurement cycle.
- echo-gpios: Definition of the GPIO for the echo (input)
This GPIO is set by the device as soon as an ultrasonic
burst is sent out and reset when the first echo is
received.
Thus this GPIO is set while the ultrasonic waves are doing
one round trip.
It needs to be an GPIO which is able to deliver an
interrupt because the time between two interrupts is
measured in the driver.
See Documentation/devicetree/bindings/gpio/gpio.txt for
information on how to specify a consumer gpio.
Example:
srf04@0 {
compatible = "devantech,srf04";
trig-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
echo-gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
};
......@@ -813,6 +813,7 @@ W: http://wiki.analog.com/
W: http://ez.analog.com/community/linux-device-drivers
S: Supported
F: drivers/iio/*/ad*
F: drivers/iio/adc/ltc2497*
X: drivers/iio/*/adjd*
F: drivers/staging/iio/*/ad*
F: drivers/staging/iio/trigger/iio-trig-bfin-timer.c
......@@ -3050,7 +3051,6 @@ CAPELLA MICROSYSTEMS LIGHT SENSOR DRIVER
M: Kevin Tsai <ktsai@capellamicro.com>
S: Maintained
F: drivers/iio/light/cm*
F: Documentation/devicetree/bindings/i2c/trivial-admin-guide/devices.rst
CAVIUM THUNDERX2 ARM64 SOC
M: Jayachandran C <jnair@caviumnetworks.com>
......@@ -3886,6 +3886,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained
F: drivers/usb/dwc3/
DEVANTECH SRF ULTRASONIC RANGER IIO DRIVER
M: Andreas Klinger <ak@it-klinger.de>
L: linux-iio@vger.kernel.org
S: Maintained
F: drivers/iio/proximity/srf*.c
DEVICE COREDUMP (DEV_COREDUMP)
M: Johannes Berg <johannes@sipsolutions.net>
L: linux-kernel@vger.kernel.org
......@@ -4131,6 +4137,18 @@ S: Maintained
F: drivers/char/dtlk.c
F: include/linux/dtlk.h
DPAA2 DATAPATH I/O (DPIO) DRIVER
M: Roy Pledge <Roy.Pledge@nxp.com>
L: linux-kernel@vger.kernel.org
S: Maintained
F: drivers/staging/fsl-mc/bus/dpio
DPAA2 ETHERNET DRIVER
M: Ioana Radulescu <ruxandra.radulescu@nxp.com>
L: linux-kernel@vger.kernel.org
S: Maintained
F: drivers/staging/fsl-dpaa2/ethernet
DPT_I2O SCSI RAID DRIVER
M: Adaptec OEM Raid Solutions <aacraid@adaptec.com>
L: linux-scsi@vger.kernel.org
......
......@@ -101,7 +101,8 @@ void __init kvm_cma_reserve(void)
(unsigned long)selected_size / SZ_1M);
align_size = HPT_ALIGN_PAGES << PAGE_SHIFT;
cma_declare_contiguous(0, selected_size, 0, align_size,
KVM_CMA_CHUNK_ORDER - PAGE_SHIFT, false, &kvm_cma);
KVM_CMA_CHUNK_ORDER - PAGE_SHIFT, false, "kvm_cma",
&kvm_cma);
}
}
......
......@@ -165,7 +165,8 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
{
int ret;
ret = cma_declare_contiguous(base, size, limit, 0, 0, fixed, res_cma);
ret = cma_declare_contiguous(base, size, limit, 0, 0, fixed,
"reserved", res_cma);
if (ret)
return ret;
......@@ -258,7 +259,7 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
return -EINVAL;
}
err = cma_init_reserved_mem(rmem->base, rmem->size, 0, &cma);
err = cma_init_reserved_mem(rmem->base, rmem->size, 0, rmem->name, &cma);
if (err) {
pr_err("Reserved memory: unable to setup CMA region\n");
return err;
......
......@@ -5,6 +5,37 @@
menu "Accelerometers"
config ADXL345
tristate
config ADXL345_I2C
tristate "Analog Devices ADXL345 3-Axis Digital Accelerometer I2C Driver"
depends on INPUT_ADXL34X=n
depends on I2C
select ADXL345
select REGMAP_I2C
help
Say Y here if you want to build support for the Analog Devices
ADXL345 3-axis digital accelerometer.
To compile this driver as a module, choose M here: the module
will be called adxl345_i2c and you will also get adxl345_core
for the core module.
config ADXL345_SPI
tristate "Analog Devices ADXL345 3-Axis Digital Accelerometer SPI Driver"
depends on INPUT_ADXL34X=n
depends on SPI
select ADXL345
select REGMAP_SPI
help
Say Y here if you want to build support for the Analog Devices
ADXL345 3-axis digital accelerometer.
To compile this driver as a module, choose M here: the module
will be called adxl345_spi and you will also get adxl345_core
for the core module.
config BMA180
tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver"
depends on I2C
......
......@@ -3,6 +3,9 @@
#
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ADXL345) += adxl345_core.o
obj-$(CONFIG_ADXL345_I2C) += adxl345_i2c.o
obj-$(CONFIG_ADXL345_SPI) += adxl345_spi.o
obj-$(CONFIG_BMA180) += bma180.o
obj-$(CONFIG_BMA220) += bma220_spi.o
obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
......
/*
* ADXL345 3-Axis Digital Accelerometer
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*/
#ifndef _ADXL345_H_
#define _ADXL345_H_
int adxl345_core_probe(struct device *dev, struct regmap *regmap,
const char *name);
int adxl345_core_remove(struct device *dev);
#endif /* _ADXL345_H_ */
/*
* ADXL345 3-Axis Digital Accelerometer IIO core driver
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*/
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/iio/iio.h>
#include "adxl345.h"
#define ADXL345_REG_DEVID 0x00
#define ADXL345_REG_POWER_CTL 0x2D
#define ADXL345_REG_DATA_FORMAT 0x31
#define ADXL345_REG_DATAX0 0x32
#define ADXL345_REG_DATAY0 0x34
#define ADXL345_REG_DATAZ0 0x36
#define ADXL345_POWER_CTL_MEASURE BIT(3)
#define ADXL345_POWER_CTL_STANDBY 0x00
#define ADXL345_DATA_FORMAT_FULL_RES BIT(3) /* Up to 13-bits resolution */
#define ADXL345_DATA_FORMAT_2G 0
#define ADXL345_DATA_FORMAT_4G 1
#define ADXL345_DATA_FORMAT_8G 2
#define ADXL345_DATA_FORMAT_16G 3
#define ADXL345_DEVID 0xE5
/*
* In full-resolution mode, scale factor is maintained at ~4 mg/LSB
* in all g ranges.
*
* At +/- 16g with 13-bit resolution, scale is computed as:
* (16 + 16) * 9.81 / (2^13 - 1) = 0.0383
*/
static const int adxl345_uscale = 38300;
struct adxl345_data {
struct regmap *regmap;
u8 data_range;
};
#define ADXL345_CHANNEL(reg, axis) { \
.type = IIO_ACCEL, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.address = reg, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
static const struct iio_chan_spec adxl345_channels[] = {
ADXL345_CHANNEL(ADXL345_REG_DATAX0, X),
ADXL345_CHANNEL(ADXL345_REG_DATAY0, Y),
ADXL345_CHANNEL(ADXL345_REG_DATAZ0, Z),
};
static int adxl345_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct adxl345_data *data = iio_priv(indio_dev);
__le16 regval;
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
/*
* Data is stored in adjacent registers:
* ADXL345_REG_DATA(X0/Y0/Z0) contain the least significant byte
* and ADXL345_REG_DATA(X0/Y0/Z0) + 1 the most significant byte
*/
ret = regmap_bulk_read(data->regmap, chan->address, &regval,
sizeof(regval));
if (ret < 0)
return ret;
*val = sign_extend32(le16_to_cpu(regval), 12);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = adxl345_uscale;
return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
static const struct iio_info adxl345_info = {
.driver_module = THIS_MODULE,
.read_raw = adxl345_read_raw,
};
int adxl345_core_probe(struct device *dev, struct regmap *regmap,
const char *name)
{
struct adxl345_data *data;
struct iio_dev *indio_dev;
u32 regval;
int ret;
ret = regmap_read(regmap, ADXL345_REG_DEVID, &regval);
if (ret < 0) {
dev_err(dev, "Error reading device ID: %d\n", ret);
return ret;
}
if (regval != ADXL345_DEVID) {
dev_err(dev, "Invalid device ID: %x, expected %x\n",
regval, ADXL345_DEVID);
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
dev_set_drvdata(dev, indio_dev);
data->regmap = regmap;
/* Enable full-resolution mode */
data->data_range = ADXL345_DATA_FORMAT_FULL_RES;
ret = regmap_write(data->regmap, ADXL345_REG_DATA_FORMAT,
data->data_range);
if (ret < 0) {
dev_err(dev, "Failed to set data range: %d\n", ret);
return ret;
}
indio_dev->dev.parent = dev;
indio_dev->name = name;
indio_dev->info = &adxl345_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = adxl345_channels;
indio_dev->num_channels = ARRAY_SIZE(adxl345_channels);
/* Enable measurement mode */
ret = regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
ADXL345_POWER_CTL_MEASURE);
if (ret < 0) {
dev_err(dev, "Failed to enable measurement mode: %d\n", ret);
return ret;
}
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(dev, "iio_device_register failed: %d\n", ret);
regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
ADXL345_POWER_CTL_STANDBY);
}
return ret;
}
EXPORT_SYMBOL_GPL(adxl345_core_probe);
int adxl345_core_remove(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adxl345_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
return regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
ADXL345_POWER_CTL_STANDBY);
}
EXPORT_SYMBOL_GPL(adxl345_core_remove);
MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer core driver");
MODULE_LICENSE("GPL v2");
/*
* ADXL345 3-Axis Digital Accelerometer I2C driver
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
* 7-bit I2C slave address: 0x1D (ALT ADDRESS pin tied to VDDIO) or
* 0x53 (ALT ADDRESS pin grounded)
*/
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include "adxl345.h"
static const struct regmap_config adxl345_i2c_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static int adxl345_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct regmap *regmap;
regmap = devm_regmap_init_i2c(client, &adxl345_i2c_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "Error initializing i2c regmap: %ld\n",
PTR_ERR(regmap));
return PTR_ERR(regmap);
}
return adxl345_core_probe(&client->dev, regmap, id ? id->name : NULL);
}
static int adxl345_i2c_remove(struct i2c_client *client)
{
return adxl345_core_remove(&client->dev);
}
static const struct i2c_device_id adxl345_i2c_id[] = {
{ "adxl345", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adxl345_i2c_id);
static const struct of_device_id adxl345_of_match[] = {
{ .compatible = "adi,adxl345" },
{ },
};
MODULE_DEVICE_TABLE(of, adxl345_of_match);
static struct i2c_driver adxl345_i2c_driver = {
.driver = {
.name = "adxl345_i2c",
.of_match_table = adxl345_of_match,
},
.probe = adxl345_i2c_probe,
.remove = adxl345_i2c_remove,
.id_table = adxl345_i2c_id,
};
module_i2c_driver(adxl345_i2c_driver);
MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer I2C driver");
MODULE_LICENSE("GPL v2");
/*
* ADXL345 3-Axis Digital Accelerometer SPI driver
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*/
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include "adxl345.h"
#define ADXL345_MAX_SPI_FREQ_HZ 5000000
static const struct regmap_config adxl345_spi_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
/* Setting bits 7 and 6 enables multiple-byte read */
.read_flag_mask = BIT(7) | BIT(6),
};
static int adxl345_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
struct regmap *regmap;
/* Bail out if max_speed_hz exceeds 5 MHz */
if (spi->max_speed_hz > ADXL345_MAX_SPI_FREQ_HZ) {
dev_err(&spi->dev, "SPI CLK, %d Hz exceeds 5 MHz\n",
spi->max_speed_hz);
return -EINVAL;
}
regmap = devm_regmap_init_spi(spi, &adxl345_spi_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
PTR_ERR(regmap));
return PTR_ERR(regmap);
}
return adxl345_core_probe(&spi->dev, regmap, id->name);
}
static int adxl345_spi_remove(struct spi_device *spi)
{
return adxl345_core_remove(&spi->dev);
}
static const struct spi_device_id adxl345_spi_id[] = {
{ "adxl345", 0 },
{ }
};
MODULE_DEVICE_TABLE(spi, adxl345_spi_id);
static const struct of_device_id adxl345_of_match[] = {
{ .compatible = "adi,adxl345" },
{ },
};
MODULE_DEVICE_TABLE(of, adxl345_of_match);
static struct spi_driver adxl345_spi_driver = {
.driver = {
.name = "adxl345_spi",
.of_match_table = adxl345_of_match,
},
.probe = adxl345_spi_probe,
.remove = adxl345_spi_remove,
.id_table = adxl345_spi_id,
};
module_spi_driver(adxl345_spi_driver);
MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer SPI driver");
MODULE_LICENSE("GPL v2");
......@@ -18,6 +18,7 @@
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/bitops.h>
#include <linux/slab.h>
......@@ -32,7 +33,7 @@
#define BMA180_DRV_NAME "bma180"
#define BMA180_IRQ_NAME "bma180_event"
enum {
enum chip_ids {
BMA180,
BMA250,
};
......@@ -41,11 +42,11 @@ struct bma180_data;
struct bma180_part_info {
const struct iio_chan_spec *channels;
unsigned num_channels;
unsigned int num_channels;
const int *scale_table;
unsigned num_scales;
unsigned int num_scales;
const int *bw_table;
unsigned num_bw;
unsigned int num_bw;
u8 int_reset_reg, int_reset_mask;
u8 sleep_reg, sleep_mask;
......@@ -408,7 +409,7 @@ static void bma250_chip_disable(struct bma180_data *data)
dev_err(&data->client->dev, "failed to disable the chip\n");
}
static ssize_t bma180_show_avail(char *buf, const int *vals, unsigned n,
static ssize_t bma180_show_avail(char *buf, const int *vals, unsigned int n,
bool micros)
{
size_t len = 0;
......@@ -707,6 +708,7 @@ static int bma180_probe(struct i2c_client *client,
{
struct bma180_data *data;
struct iio_dev *indio_dev;
enum chip_ids chip;
int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
......@@ -716,7 +718,11 @@ static int bma180_probe(struct i2c_client *client,
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
data->part_info = &bma180_part_info[id->driver_data];
if (client->dev.of_node)
chip = (enum chip_ids)of_device_get_match_data(&client->dev);
else
chip = id->driver_data;
data->part_info = &bma180_part_info[chip];
ret = data->part_info->chip_config(data);
if (ret < 0)
......@@ -844,10 +850,24 @@ static struct i2c_device_id bma180_ids[] = {
MODULE_DEVICE_TABLE(i2c, bma180_ids);
static const struct of_device_id bma180_of_match[] = {
{
.compatible = "bosch,bma180",
.data = (void *)BMA180
},
{
.compatible = "bosch,bma250",
.data = (void *)BMA250
},
{ }
};
MODULE_DEVICE_TABLE(of, bma180_of_match);
static struct i2c_driver bma180_driver = {
.driver = {
.name = "bma180",
.pm = BMA180_PM_OPS,
.of_match_table = bma180_of_match,
},
.probe = bma180_probe,
.remove = bma180_remove,
......
......@@ -41,12 +41,20 @@ static const struct i2c_device_id mma7455_i2c_ids[] = {
};
MODULE_DEVICE_TABLE(i2c, mma7455_i2c_ids);
static const struct of_device_id mma7455_of_match[] = {
{ .compatible = "fsl,mma7455" },
{ .compatible = "fsl,mma7456" },
{ }
};
MODULE_DEVICE_TABLE(of, mma7455_of_match);
static struct i2c_driver mma7455_i2c_driver = {
.probe = mma7455_i2c_probe,
.remove = mma7455_i2c_remove,
.id_table = mma7455_i2c_ids,
.driver = {
.name = "mma7455-i2c",
.of_match_table = mma7455_of_match,
},
};
module_i2c_driver(mma7455_i2c_driver);
......
......@@ -253,6 +253,12 @@ static const struct i2c_device_id mma7660_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, mma7660_i2c_id);
static const struct of_device_id mma7660_of_match[] = {
{ .compatible = "fsl,mma7660" },
{ }
};
MODULE_DEVICE_TABLE(of, mma7660_of_match);
static const struct acpi_device_id mma7660_acpi_id[] = {
{"MMA7660", 0},
{}
......@@ -264,6 +270,7 @@ static struct i2c_driver mma7660_driver = {
.driver = {
.name = "mma7660",
.pm = MMA7660_PM_OPS,
.of_match_table = mma7660_of_match,
.acpi_match_table = ACPI_PTR(mma7660_acpi_id),
},
.probe = mma7660_probe,
......
......@@ -130,6 +130,17 @@ config AD799X
To compile this driver as a module, choose M here: the module will be
called ad799x.
config ASPEED_ADC
tristate "Aspeed ADC"
depends on ARCH_ASPEED || COMPILE_TEST
depends on COMMON_CLK
help
If you say yes here you get support for the ADC included in Aspeed
BMC SoCs.
To compile this driver as a module, choose M here: the module will be
called aspeed_adc.
config AT91_ADC
tristate "Atmel AT91 ADC"
depends on ARCH_AT91
......@@ -205,6 +216,17 @@ config CC10001_ADC
This driver can also be built as a module. If so, the module will be
called cc10001_adc.
config CPCAP_ADC
tristate "Motorola CPCAP PMIC ADC driver"
depends on MFD_CPCAP
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for Motorola CPCAP PMIC ADC.
This driver can also be built as a module. If so, the module will be
called cpcap-adc.
config DA9150_GPADC
tristate "Dialog DA9150 GPADC driver support"
depends on MFD_DA9150
......@@ -328,6 +350,18 @@ config LPC18XX_ADC
To compile this driver as a module, choose M here: the module will be
called lpc18xx_adc.
config LPC32XX_ADC
tristate "NXP LPC32XX ADC"
depends on ARCH_LPC32XX || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to build support for the integrated ADC inside the
LPC32XX SoC. Note that this feature uses the same hardware as the
touchscreen driver, so you should either select only one of the two
drivers (lpc32xx_adc or lpc32xx_ts) or, in the OpenFirmware case,
activate only one via device tree selection. Provides direct access
via sysfs.
config LTC2485
tristate "Linear Technology LTC2485 ADC driver"
depends on I2C
......@@ -337,6 +371,16 @@ config LTC2485
To compile this driver as a module, choose M here: the module will be
called ltc2485.
config LTC2497
tristate "Linear Technology LTC2497 ADC driver"
depends on I2C
help
Say yes here to build support for Linear Technology LTC2497
16-Bit 8-/16-Channel Delta Sigma ADC.
To compile this driver as a module, choose M here: the module will be
called ltc2497.
config MAX1027
tristate "Maxim max1027 ADC driver"
depends on SPI
......@@ -358,6 +402,18 @@ config MAX11100
To compile this driver as a module, choose M here: the module will be
called max11100.
config MAX1118
tristate "Maxim max1117/max1118/max1119 ADCs driver"
depends on SPI
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for Maxim max1117/max1118/max1119
8-bit, dual-channel ADCs.
To compile this driver as a module, choose M here: the module will be
called max1118.
config MAX1363
tristate "Maxim max1363 ADC driver"
depends on I2C
......@@ -377,6 +433,16 @@ config MAX1363
To compile this driver as a module, choose M here: the module will be
called max1363.
config MAX9611
tristate "Maxim max9611/max9612 ADC driver"
depends on I2C
help
Say yes here to build support for Maxim max9611/max9612 current sense
amplifier with 12-bits ADC interface.
To compile this driver as a module, choose M here: the module will be
called max9611.
config MCP320X
tristate "Microchip Technology MCP3x01/02/04/08"
depends on SPI
......@@ -451,6 +517,20 @@ config PALMAS_GPADC
is used in smartphones and tablets and supports a 16 channel
general purpose ADC.
config QCOM_VADC_COMMON
tristate
config QCOM_PM8XXX_XOADC
tristate "Qualcomm SSBI PM8xxx PMIC XOADCs"
depends on MFD_PM8XXX
select QCOM_VADC_COMMON
help
ADC driver for the XOADC portions of the Qualcomm PM8xxx PMICs
using SSBI transport: PM8018, PM8038, PM8058, PM8921.
To compile this driver as a module, choose M here: the module
will be called qcom-pm8xxx-xoadc.
config QCOM_SPMI_IADC
tristate "Qualcomm SPMI PMIC current ADC"
depends on SPMI
......@@ -469,6 +549,7 @@ config QCOM_SPMI_VADC
tristate "Qualcomm SPMI PMIC voltage ADC"
depends on SPMI
select REGMAP_SPMI
select QCOM_VADC_COMMON
help
This is the IIO Voltage ADC driver for Qualcomm QPNP VADC Chip.
......@@ -503,6 +584,17 @@ config ROCKCHIP_SARADC
To compile this driver as a module, choose M here: the
module will be called rockchip_saradc.
config SPEAR_ADC
tristate "ST SPEAr ADC"
depends on PLAT_SPEAR || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to build support for the integrated ADC inside the
ST SPEAr SoC. Provides direct access via sysfs.
To compile this driver as a module, choose M here: the
module will be called spear_adc.
config STM32_ADC_CORE
tristate "STMicroelectronics STM32 adc core"
depends on ARCH_STM32 || COMPILE_TEST
......@@ -532,7 +624,7 @@ config STM32_ADC
config STX104
tristate "Apex Embedded Systems STX104 driver"
depends on X86 && ISA_BUS_API
depends on PC104 && X86 && ISA_BUS_API
select GPIOLIB
help
Say yes here to build support for the Apex Embedded Systems STX104
......@@ -545,6 +637,24 @@ config STX104
The base port addresses for the devices may be configured via the base
array module parameter.
config SUN4I_GPADC
tristate "Support for the Allwinner SoCs GPADC"
depends on IIO
depends on MFD_SUN4I_GPADC || MACH_SUN8I
depends on THERMAL || !THERMAL_OF
help
Say yes here to build support for Allwinner (A10, A13 and A31) SoCs
GPADC. This ADC provides 4 channels which can be used as an ADC or as
a touchscreen input and one channel for thermal sensor.
The thermal sensor slows down ADC readings and can be disabled by
disabling CONFIG_THERMAL_OF. However, the thermal sensor should be
enabled by default since the SoC temperature is usually more critical
than ADC readings.
To compile this driver as a module, choose M here: the module will be
called sun4i-gpadc-iio.
config TI_ADC081C
tristate "Texas Instruments ADC081C/ADC101C/ADC121C family"
depends on I2C
......
......@@ -14,6 +14,7 @@ obj-$(CONFIG_AD7791) += ad7791.o
obj-$(CONFIG_AD7793) += ad7793.o
obj-$(CONFIG_AD7887) += ad7887.o
obj-$(CONFIG_AD799X) += ad799x.o
obj-$(CONFIG_ASPEED_ADC) += aspeed_adc.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o
obj-$(CONFIG_AXP20X_ADC) += axp20x_adc.o
......@@ -21,6 +22,7 @@ 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_CC10001_ADC) += cc10001_adc.o
obj-$(CONFIG_CPCAP_ADC) += cpcap-adc.o
obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o
obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
......@@ -31,10 +33,14 @@ obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
obj-$(CONFIG_LTC2485) += ltc2485.o
obj-$(CONFIG_LTC2497) += ltc2497.o
obj-$(CONFIG_MAX1027) += max1027.o
obj-$(CONFIG_MAX11100) += max11100.o
obj-$(CONFIG_MAX1118) += max1118.o
obj-$(CONFIG_MAX1363) += max1363.o
obj-$(CONFIG_MAX9611) += max9611.o
obj-$(CONFIG_MCP320X) += mcp320x.o
obj-$(CONFIG_MCP3422) += mcp3422.o
obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o
......@@ -44,10 +50,14 @@ obj-$(CONFIG_MXS_LRADC_ADC) += mxs-lradc-adc.o
obj-$(CONFIG_NAU7802) += nau7802.o
obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
obj-$(CONFIG_QCOM_VADC_COMMON) += qcom-vadc-common.o
obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
obj-$(CONFIG_QCOM_PM8XXX_XOADC) += qcom-pm8xxx-xoadc.o
obj-$(CONFIG_RCAR_GYRO_ADC) += rcar-gyroadc.o
obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
obj-$(CONFIG_SPEAR_ADC) += spear_adc.o
obj-$(CONFIG_STX104) += stx104.o
obj-$(CONFIG_SUN4I_GPADC) += sun4i-gpadc-iio.o
obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
obj-$(CONFIG_STM32_ADC) += stm32-adc.o
obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
......
......@@ -520,7 +520,7 @@ static struct attribute *ad799x_event_attributes[] = {
NULL,
};
static struct attribute_group ad799x_event_attrs_group = {
static const struct attribute_group ad799x_event_attrs_group = {
.attrs = ad799x_event_attributes,
};
......
/*
* Aspeed AST2400/2500 ADC
*
* Copyright (C) 2017 Google, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/iio/iio.h>
#include <linux/iio/driver.h>
#define ASPEED_RESOLUTION_BITS 10
#define ASPEED_CLOCKS_PER_SAMPLE 12
#define ASPEED_REG_ENGINE_CONTROL 0x00
#define ASPEED_REG_INTERRUPT_CONTROL 0x04
#define ASPEED_REG_VGA_DETECT_CONTROL 0x08
#define ASPEED_REG_CLOCK_CONTROL 0x0C
#define ASPEED_REG_MAX 0xC0
#define ASPEED_OPERATION_MODE_POWER_DOWN (0x0 << 1)
#define ASPEED_OPERATION_MODE_STANDBY (0x1 << 1)
#define ASPEED_OPERATION_MODE_NORMAL (0x7 << 1)
#define ASPEED_ENGINE_ENABLE BIT(0)
struct aspeed_adc_model_data {
const char *model_name;
unsigned int min_sampling_rate; // Hz
unsigned int max_sampling_rate; // Hz
unsigned int vref_voltage; // mV
};
struct aspeed_adc_data {
struct device *dev;
void __iomem *base;
spinlock_t clk_lock;
struct clk_hw *clk_prescaler;
struct clk_hw *clk_scaler;
};
#define ASPEED_CHAN(_idx, _data_reg_addr) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (_idx), \
.address = (_data_reg_addr), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
}
static const struct iio_chan_spec aspeed_adc_iio_channels[] = {
ASPEED_CHAN(0, 0x10),
ASPEED_CHAN(1, 0x12),
ASPEED_CHAN(2, 0x14),
ASPEED_CHAN(3, 0x16),
ASPEED_CHAN(4, 0x18),
ASPEED_CHAN(5, 0x1A),
ASPEED_CHAN(6, 0x1C),
ASPEED_CHAN(7, 0x1E),
ASPEED_CHAN(8, 0x20),
ASPEED_CHAN(9, 0x22),
ASPEED_CHAN(10, 0x24),
ASPEED_CHAN(11, 0x26),
ASPEED_CHAN(12, 0x28),
ASPEED_CHAN(13, 0x2A),
ASPEED_CHAN(14, 0x2C),
ASPEED_CHAN(15, 0x2E),
};
static int aspeed_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct aspeed_adc_data *data = iio_priv(indio_dev);
const struct aspeed_adc_model_data *model_data =
of_device_get_match_data(data->dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
*val = readw(data->base + chan->address);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = model_data->vref_voltage;
*val2 = ASPEED_RESOLUTION_BITS;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_SAMP_FREQ:
*val = clk_get_rate(data->clk_scaler->clk) /
ASPEED_CLOCKS_PER_SAMPLE;
return IIO_VAL_INT;
default:
return -EINVAL;
}
}
static int aspeed_adc_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct aspeed_adc_data *data = iio_priv(indio_dev);
const struct aspeed_adc_model_data *model_data =
of_device_get_match_data(data->dev);
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
if (val < model_data->min_sampling_rate ||
val > model_data->max_sampling_rate)
return -EINVAL;
clk_set_rate(data->clk_scaler->clk,
val * ASPEED_CLOCKS_PER_SAMPLE);
return 0;
case IIO_CHAN_INFO_SCALE:
case IIO_CHAN_INFO_RAW:
/*
* Technically, these could be written but the only reasons
* for doing so seem better handled in userspace. EPERM is
* returned to signal this is a policy choice rather than a
* hardware limitation.
*/
return -EPERM;
default:
return -EINVAL;
}
}
static int aspeed_adc_reg_access(struct iio_dev *indio_dev,
unsigned int reg, unsigned int writeval,
unsigned int *readval)
{
struct aspeed_adc_data *data = iio_priv(indio_dev);
if (!readval || reg % 4 || reg > ASPEED_REG_MAX)
return -EINVAL;
*readval = readl(data->base + reg);
return 0;
}
static const struct iio_info aspeed_adc_iio_info = {
.driver_module = THIS_MODULE,
.read_raw = aspeed_adc_read_raw,
.write_raw = aspeed_adc_write_raw,
.debugfs_reg_access = aspeed_adc_reg_access,
};
static int aspeed_adc_probe(struct platform_device *pdev)
{
struct iio_dev *indio_dev;
struct aspeed_adc_data *data;
const struct aspeed_adc_model_data *model_data;
struct resource *res;
const char *clk_parent_name;
int ret;
u32 adc_engine_control_reg_val;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
data->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(data->base))
return PTR_ERR(data->base);
/* Register ADC clock prescaler with source specified by device tree. */
spin_lock_init(&data->clk_lock);
clk_parent_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
data->clk_prescaler = clk_hw_register_divider(
&pdev->dev, "prescaler", clk_parent_name, 0,
data->base + ASPEED_REG_CLOCK_CONTROL,
17, 15, 0, &data->clk_lock);
if (IS_ERR(data->clk_prescaler))
return PTR_ERR(data->clk_prescaler);
/*
* Register ADC clock scaler downstream from the prescaler. Allow rate
* setting to adjust the prescaler as well.
*/
data->clk_scaler = clk_hw_register_divider(
&pdev->dev, "scaler", "prescaler",
CLK_SET_RATE_PARENT,
data->base + ASPEED_REG_CLOCK_CONTROL,
0, 10, 0, &data->clk_lock);
if (IS_ERR(data->clk_scaler)) {
ret = PTR_ERR(data->clk_scaler);
goto scaler_error;
}
/* Start all channels in normal mode. */
clk_prepare_enable(data->clk_scaler->clk);
adc_engine_control_reg_val = GENMASK(31, 16) |
ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE;
writel(adc_engine_control_reg_val,
data->base + ASPEED_REG_ENGINE_CONTROL);
model_data = of_device_get_match_data(&pdev->dev);
indio_dev->name = model_data->model_name;
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &aspeed_adc_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = aspeed_adc_iio_channels;
indio_dev->num_channels = ARRAY_SIZE(aspeed_adc_iio_channels);
ret = iio_device_register(indio_dev);
if (ret)
goto iio_register_error;
return 0;
iio_register_error:
writel(ASPEED_OPERATION_MODE_POWER_DOWN,
data->base + ASPEED_REG_ENGINE_CONTROL);
clk_disable_unprepare(data->clk_scaler->clk);
clk_hw_unregister_divider(data->clk_scaler);
scaler_error:
clk_hw_unregister_divider(data->clk_prescaler);
return ret;
}
static int aspeed_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct aspeed_adc_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
writel(ASPEED_OPERATION_MODE_POWER_DOWN,
data->base + ASPEED_REG_ENGINE_CONTROL);
clk_disable_unprepare(data->clk_scaler->clk);
clk_hw_unregister_divider(data->clk_scaler);
clk_hw_unregister_divider(data->clk_prescaler);
return 0;
}
static const struct aspeed_adc_model_data ast2400_model_data = {
.model_name = "ast2400-adc",
.vref_voltage = 2500, // mV
.min_sampling_rate = 10000,
.max_sampling_rate = 500000,
};
static const struct aspeed_adc_model_data ast2500_model_data = {
.model_name = "ast2500-adc",
.vref_voltage = 1800, // mV
.min_sampling_rate = 1,
.max_sampling_rate = 1000000,
};
static const struct of_device_id aspeed_adc_matches[] = {
{ .compatible = "aspeed,ast2400-adc", .data = &ast2400_model_data },
{ .compatible = "aspeed,ast2500-adc", .data = &ast2500_model_data },
{},
};
MODULE_DEVICE_TABLE(of, aspeed_adc_matches);
static struct platform_driver aspeed_adc_driver = {
.probe = aspeed_adc_probe,
.remove = aspeed_adc_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = aspeed_adc_matches,
}
};
module_platform_driver(aspeed_adc_driver);
MODULE_AUTHOR("Rick Altherr <raltherr@google.com>");
MODULE_DESCRIPTION("Aspeed AST2400/2500 ADC Driver");
MODULE_LICENSE("GPL");
This diff is collapsed.
......@@ -579,7 +579,7 @@ static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev, int *x, int *y)
static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
{
struct exynos_adc *info = (struct exynos_adc *)dev_id;
struct exynos_adc *info = dev_id;
u32 mask = info->data->mask;
/* Read value */
......
......@@ -369,7 +369,7 @@ static struct attribute *hx711_attributes[] = {
NULL,
};
static struct attribute_group hx711_attribute_group = {
static const struct attribute_group hx711_attribute_group = {
.attrs = hx711_attributes,
};
......
......@@ -365,7 +365,7 @@ static int imx7d_adc_read_data(struct imx7d_adc *info)
static irqreturn_t imx7d_adc_isr(int irq, void *dev_id)
{
struct imx7d_adc *info = (struct imx7d_adc *)dev_id;
struct imx7d_adc *info = dev_id;
int status;
status = readl(info->regs + IMX7D_REG_ADC_INT_STATUS);
......
......@@ -28,6 +28,7 @@
#include <linux/iio/sysfs.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/util_macros.h>
......@@ -635,6 +636,7 @@ static int ina2xx_probe(struct i2c_client *client,
struct iio_dev *indio_dev;
struct iio_buffer *buffer;
unsigned int val;
enum ina2xx_ids type;
int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
......@@ -652,7 +654,11 @@ static int ina2xx_probe(struct i2c_client *client,
return PTR_ERR(chip->regmap);
}
chip->config = &ina2xx_config[id->driver_data];
if (client->dev.of_node)
type = (enum ina2xx_ids)of_device_get_match_data(&client->dev);
else
type = id->driver_data;
chip->config = &ina2xx_config[type];
mutex_init(&chip->state_lock);
......@@ -726,9 +732,35 @@ static const struct i2c_device_id ina2xx_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ina2xx_id);
static const struct of_device_id ina2xx_of_match[] = {
{
.compatible = "ti,ina219",
.data = (void *)ina219
},
{
.compatible = "ti,ina220",
.data = (void *)ina219
},
{
.compatible = "ti,ina226",
.data = (void *)ina226
},
{
.compatible = "ti,ina230",
.data = (void *)ina226
},
{
.compatible = "ti,ina231",
.data = (void *)ina226
},
{},
};
MODULE_DEVICE_TABLE(of, ina2xx_of_match);
static struct i2c_driver ina2xx_driver = {
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = ina2xx_of_match,
},
.probe = ina2xx_probe,
.remove = ina2xx_remove,
......
......@@ -38,27 +38,30 @@
/*
* LPC32XX registers definitions
*/
#define LPC32XX_ADC_SELECT(x) ((x) + 0x04)
#define LPC32XX_ADC_CTRL(x) ((x) + 0x08)
#define LPC32XX_ADC_VALUE(x) ((x) + 0x48)
/* Bit definitions for LPC32XX_ADC_SELECT: */
#define AD_REFm 0x00000200 /* constant, always write this value! */
#define AD_REFp 0x00000080 /* constant, always write this value! */
#define AD_IN 0x00000010 /* multiple of this is the */
/* channel number: 0, 1, 2 */
#define AD_INTERNAL 0x00000004 /* constant, always write this value! */
/* Bit definitions for LPC32XX_ADC_CTRL: */
#define AD_STROBE 0x00000002
#define AD_PDN_CTRL 0x00000004
/* Bit definitions for LPC32XX_ADC_VALUE: */
#define ADC_VALUE_MASK 0x000003FF
#define MOD_NAME "lpc32xx-adc"
struct lpc32xx_adc_info {
#define LPC32XXAD_SELECT(x) ((x) + 0x04)
#define LPC32XXAD_CTRL(x) ((x) + 0x08)
#define LPC32XXAD_VALUE(x) ((x) + 0x48)
/* Bit definitions for LPC32XXAD_SELECT: */
/* constant, always write this value! */
#define LPC32XXAD_REFm 0x00000200
/* constant, always write this value! */
#define LPC32XXAD_REFp 0x00000080
/* multiple of this is the channel number: 0, 1, 2 */
#define LPC32XXAD_IN 0x00000010
/* constant, always write this value! */
#define LPC32XXAD_INTERNAL 0x00000004
/* Bit definitions for LPC32XXAD_CTRL: */
#define LPC32XXAD_STROBE 0x00000002
#define LPC32XXAD_PDN_CTRL 0x00000004
/* Bit definitions for LPC32XXAD_VALUE: */
#define LPC32XXAD_VALUE_MASK 0x000003FF
#define LPC32XXAD_NAME "lpc32xx-adc"
struct lpc32xx_adc_state {
void __iomem *adc_base;
struct clk *clk;
struct completion completion;
......@@ -72,20 +75,21 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
int *val2,
long mask)
{
struct lpc32xx_adc_info *info = iio_priv(indio_dev);
struct lpc32xx_adc_state *st = iio_priv(indio_dev);
if (mask == IIO_CHAN_INFO_RAW) {
mutex_lock(&indio_dev->mlock);
clk_prepare_enable(info->clk);
clk_prepare_enable(st->clk);
/* Measurement setup */
__raw_writel(AD_INTERNAL | (chan->address) | AD_REFp | AD_REFm,
LPC32XX_ADC_SELECT(info->adc_base));
__raw_writel(LPC32XXAD_INTERNAL | (chan->address) |
LPC32XXAD_REFp | LPC32XXAD_REFm,
LPC32XXAD_SELECT(st->adc_base));
/* Trigger conversion */
__raw_writel(AD_PDN_CTRL | AD_STROBE,
LPC32XX_ADC_CTRL(info->adc_base));
wait_for_completion(&info->completion); /* set by ISR */
clk_disable_unprepare(info->clk);
*val = info->value;
__raw_writel(LPC32XXAD_PDN_CTRL | LPC32XXAD_STROBE,
LPC32XXAD_CTRL(st->adc_base));
wait_for_completion(&st->completion); /* set by ISR */
clk_disable_unprepare(st->clk);
*val = st->value;
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
......@@ -104,7 +108,7 @@ static const struct iio_info lpc32xx_adc_iio_info = {
.indexed = 1, \
.channel = _index, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.address = AD_IN * _index, \
.address = LPC32XXAD_IN * _index, \
.scan_index = _index, \
}
......@@ -116,19 +120,19 @@ static const struct iio_chan_spec lpc32xx_adc_iio_channels[] = {
static irqreturn_t lpc32xx_adc_isr(int irq, void *dev_id)
{
struct lpc32xx_adc_info *info = dev_id;
struct lpc32xx_adc_state *st = dev_id;
/* Read value and clear irq */
info->value = __raw_readl(LPC32XX_ADC_VALUE(info->adc_base)) &
ADC_VALUE_MASK;
complete(&info->completion);
st->value = __raw_readl(LPC32XXAD_VALUE(st->adc_base)) &
LPC32XXAD_VALUE_MASK;
complete(&st->completion);
return IRQ_HANDLED;
}
static int lpc32xx_adc_probe(struct platform_device *pdev)
{
struct lpc32xx_adc_info *info = NULL;
struct lpc32xx_adc_state *st = NULL;
struct resource *res;
int retval = -ENODEV;
struct iio_dev *iodev = NULL;
......@@ -140,23 +144,23 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
return -ENXIO;
}
iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
if (!iodev)
return -ENOMEM;
info = iio_priv(iodev);
st = iio_priv(iodev);
info->adc_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (!info->adc_base) {
st->adc_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (!st->adc_base) {
dev_err(&pdev->dev, "failed mapping memory\n");
return -EBUSY;
}
info->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(info->clk)) {
st->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(st->clk)) {
dev_err(&pdev->dev, "failed getting clock\n");
return PTR_ERR(info->clk);
return PTR_ERR(st->clk);
}
irq = platform_get_irq(pdev, 0);
......@@ -166,7 +170,7 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
}
retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0,
MOD_NAME, info);
LPC32XXAD_NAME, st);
if (retval < 0) {
dev_err(&pdev->dev, "failed requesting interrupt\n");
return retval;
......@@ -174,9 +178,9 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, iodev);
init_completion(&info->completion);
init_completion(&st->completion);
iodev->name = MOD_NAME;
iodev->name = LPC32XXAD_NAME;
iodev->dev.parent = &pdev->dev;
iodev->info = &lpc32xx_adc_iio_info;
iodev->modes = INDIO_DIRECT_MODE;
......@@ -203,7 +207,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_adc_match);
static struct platform_driver lpc32xx_adc_driver = {
.probe = lpc32xx_adc_probe,
.driver = {
.name = MOD_NAME,
.name = LPC32XXAD_NAME,
.of_match_table = of_match_ptr(lpc32xx_adc_match),
},
};
......
/*
* ltc2497.c - Driver for Analog Devices/Linear Technology LTC2497 ADC
*
* Copyright (C) 2017 Analog Devices Inc.
*
* Licensed under the GPL-2.
*
* Datasheet: http://cds.linear.com/docs/en/datasheet/2497fd.pdf
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regulator/consumer.h>
#define LTC2497_ENABLE 0xA0
#define LTC2497_SGL BIT(4)
#define LTC2497_DIFF 0
#define LTC2497_SIGN BIT(3)
#define LTC2497_CONFIG_DEFAULT LTC2497_ENABLE
#define LTC2497_CONVERSION_TIME_MS 150ULL
struct ltc2497_st {
struct i2c_client *client;
struct regulator *ref;
ktime_t time_prev;
u8 addr_prev;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
__be32 buf ____cacheline_aligned;
};
static int ltc2497_wait_conv(struct ltc2497_st *st)
{
s64 time_elapsed;
time_elapsed = ktime_ms_delta(ktime_get(), st->time_prev);
if (time_elapsed < LTC2497_CONVERSION_TIME_MS) {
/* delay if conversion time not passed
* since last read or write
*/
if (msleep_interruptible(
LTC2497_CONVERSION_TIME_MS - time_elapsed))
return -ERESTARTSYS;
return 0;
}
if (time_elapsed - LTC2497_CONVERSION_TIME_MS <= 0) {
/* We're in automatic mode -
* so the last reading is stil not outdated
*/
return 0;
}
return 1;
}
static int ltc2497_read(struct ltc2497_st *st, u8 address, int *val)
{
struct i2c_client *client = st->client;
int ret;
ret = ltc2497_wait_conv(st);
if (ret < 0)
return ret;
if (ret || st->addr_prev != address) {
ret = i2c_smbus_write_byte(st->client,
LTC2497_ENABLE | address);
if (ret < 0)
return ret;
st->addr_prev = address;
if (msleep_interruptible(LTC2497_CONVERSION_TIME_MS))
return -ERESTARTSYS;
}
ret = i2c_master_recv(client, (char *)&st->buf, 3);
if (ret < 0) {
dev_err(&client->dev, "i2c_master_recv failed\n");
return ret;
}
st->time_prev = ktime_get();
/* convert and shift the result,
* and finally convert from offset binary to signed integer
*/
*val = (be32_to_cpu(st->buf) >> 14) - (1 << 17);
return ret;
}
static int ltc2497_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct ltc2497_st *st = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
ret = ltc2497_read(st, chan->address, val);
mutex_unlock(&indio_dev->mlock);
if (ret < 0)
return ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
ret = regulator_get_voltage(st->ref);
if (ret < 0)
return ret;
*val = ret / 1000;
*val2 = 17;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
}
#define LTC2497_CHAN(_chan, _addr) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (_chan), \
.address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
#define LTC2497_CHAN_DIFF(_chan, _addr) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 1 : 0), \
.channel2 = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 0 : 1),\
.address = (_addr | _chan), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.differential = 1, \
}
static const struct iio_chan_spec ltc2497_channel[] = {
LTC2497_CHAN(0, LTC2497_SGL),
LTC2497_CHAN(1, LTC2497_SGL),
LTC2497_CHAN(2, LTC2497_SGL),
LTC2497_CHAN(3, LTC2497_SGL),
LTC2497_CHAN(4, LTC2497_SGL),
LTC2497_CHAN(5, LTC2497_SGL),
LTC2497_CHAN(6, LTC2497_SGL),
LTC2497_CHAN(7, LTC2497_SGL),
LTC2497_CHAN(8, LTC2497_SGL),
LTC2497_CHAN(9, LTC2497_SGL),
LTC2497_CHAN(10, LTC2497_SGL),
LTC2497_CHAN(11, LTC2497_SGL),
LTC2497_CHAN(12, LTC2497_SGL),
LTC2497_CHAN(13, LTC2497_SGL),
LTC2497_CHAN(14, LTC2497_SGL),
LTC2497_CHAN(15, LTC2497_SGL),
LTC2497_CHAN_DIFF(0, LTC2497_DIFF),
LTC2497_CHAN_DIFF(1, LTC2497_DIFF),
LTC2497_CHAN_DIFF(2, LTC2497_DIFF),
LTC2497_CHAN_DIFF(3, LTC2497_DIFF),
LTC2497_CHAN_DIFF(4, LTC2497_DIFF),
LTC2497_CHAN_DIFF(5, LTC2497_DIFF),
LTC2497_CHAN_DIFF(6, LTC2497_DIFF),
LTC2497_CHAN_DIFF(7, LTC2497_DIFF),
LTC2497_CHAN_DIFF(0, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(1, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(2, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(3, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(4, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(5, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(6, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(7, LTC2497_DIFF | LTC2497_SIGN),
};
static const struct iio_info ltc2497_info = {
.read_raw = ltc2497_read_raw,
.driver_module = THIS_MODULE,
};
static int ltc2497_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct iio_dev *indio_dev;
struct ltc2497_st *st;
int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
I2C_FUNC_SMBUS_WRITE_BYTE))
return -EOPNOTSUPP;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
st->client = client;
indio_dev->dev.parent = &client->dev;
indio_dev->name = id->name;
indio_dev->info = &ltc2497_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = ltc2497_channel;
indio_dev->num_channels = ARRAY_SIZE(ltc2497_channel);
st->ref = devm_regulator_get(&client->dev, "vref");
if (IS_ERR(st->ref))
return PTR_ERR(st->ref);
ret = regulator_enable(st->ref);
if (ret < 0)
return ret;
ret = i2c_smbus_write_byte(st->client, LTC2497_CONFIG_DEFAULT);
if (ret < 0)
goto err_regulator_disable;
st->addr_prev = LTC2497_CONFIG_DEFAULT;
st->time_prev = ktime_get();
ret = iio_device_register(indio_dev);
if (ret < 0)
goto err_regulator_disable;
return 0;
err_regulator_disable:
regulator_disable(st->ref);
return ret;
}
static int ltc2497_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct ltc2497_st *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
regulator_disable(st->ref);
return 0;
}
static const struct i2c_device_id ltc2497_id[] = {
{ "ltc2497", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ltc2497_id);
static const struct of_device_id ltc2497_of_match[] = {
{ .compatible = "lltc,ltc2497", },
{},
};
MODULE_DEVICE_TABLE(of, ltc2497_of_match);
static struct i2c_driver ltc2497_driver = {
.driver = {
.name = "ltc2497",
.of_match_table = of_match_ptr(ltc2497_of_match),
},
.probe = ltc2497_probe,
.remove = ltc2497_remove,
.id_table = ltc2497_id,
};
module_i2c_driver(ltc2497_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Linear Technology LTC2497 ADC driver");
MODULE_LICENSE("GPL v2");
......@@ -364,7 +364,7 @@ static int max1027_set_trigger_state(struct iio_trigger *trig, bool state)
static irqreturn_t max1027_trigger_handler(int irq, void *private)
{
struct iio_poll_func *pf = (struct iio_poll_func *)private;
struct iio_poll_func *pf = private;
struct iio_dev *indio_dev = pf->indio_dev;
struct max1027_state *st = iio_priv(indio_dev);
......
......@@ -124,8 +124,8 @@ static int max11100_probe(struct spi_device *spi)
indio_dev->name = "max11100";
indio_dev->info = &max11100_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = max11100_channels,
indio_dev->num_channels = ARRAY_SIZE(max11100_channels),
indio_dev->channels = max11100_channels;
indio_dev->num_channels = ARRAY_SIZE(max11100_channels);
state->vref_reg = devm_regulator_get(&spi->dev, "vref");
if (IS_ERR(state->vref_reg))
......@@ -167,7 +167,6 @@ MODULE_DEVICE_TABLE(of, max11100_ids);
static struct spi_driver max11100_driver = {
.driver = {
.name = "max11100",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(max11100_ids),
},
.probe = max11100_probe,
......
/*
* MAX1117/MAX1118/MAX1119 8-bit, dual-channel ADCs driver
*
* Copyright (c) 2017 Akinobu Mita <akinobu.mita@gmail.com>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
* Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX1117-MAX1119.pdf
*
* SPI interface connections
*
* SPI MAXIM
* Master Direction MAX1117/8/9
* ------ --------- -----------
* nCS --> CNVST
* SCK --> SCLK
* MISO <-- DOUT
* ------ --------- -----------
*/
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/regulator/consumer.h>
enum max1118_id {
max1117,
max1118,
max1119,
};
struct max1118 {
struct spi_device *spi;
struct mutex lock;
struct regulator *reg;
u8 data ____cacheline_aligned;
};
#define MAX1118_CHANNEL(ch) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (ch), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.scan_index = ch, \
.scan_type = { \
.sign = 'u', \
.realbits = 8, \
.storagebits = 8, \
}, \
}
static const struct iio_chan_spec max1118_channels[] = {
MAX1118_CHANNEL(0),
MAX1118_CHANNEL(1),
IIO_CHAN_SOFT_TIMESTAMP(2),
};
static int max1118_read(struct spi_device *spi, int channel)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct max1118 *adc = iio_priv(indio_dev);
struct spi_transfer xfers[] = {
/*
* To select CH1 for conversion, CNVST pin must be brought high
* and low for a second time.
*/
{
.len = 0,
.delay_usecs = 1, /* > CNVST Low Time 100 ns */
.cs_change = 1,
},
/*
* The acquisition interval begins with the falling edge of
* CNVST. The total acquisition and conversion process takes
* <7.5us.
*/
{
.len = 0,
.delay_usecs = 8,
},
{
.rx_buf = &adc->data,
.len = 1,
},
};
int ret;
if (channel == 0)
ret = spi_sync_transfer(spi, xfers + 1, 2);
else
ret = spi_sync_transfer(spi, xfers, 3);
if (ret)
return ret;
return adc->data;
}
static int max1118_get_vref_mV(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct max1118 *adc = iio_priv(indio_dev);
const struct spi_device_id *id = spi_get_device_id(spi);
int vref_uV;
switch (id->driver_data) {
case max1117:
return 2048;
case max1119:
return 4096;
case max1118:
vref_uV = regulator_get_voltage(adc->reg);
if (vref_uV < 0)
return vref_uV;
return vref_uV / 1000;
}
return -ENODEV;
}
static int max1118_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct max1118 *adc = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&adc->lock);
*val = max1118_read(adc->spi, chan->channel);
mutex_unlock(&adc->lock);
if (*val < 0)
return *val;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = max1118_get_vref_mV(adc->spi);
if (*val < 0)
return *val;
*val2 = 8;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
static const struct iio_info max1118_info = {
.read_raw = max1118_read_raw,
.driver_module = THIS_MODULE,
};
static irqreturn_t max1118_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct max1118 *adc = iio_priv(indio_dev);
u8 data[16] = { }; /* 2x 8-bit ADC data + padding + 8 bytes timestamp */
int scan_index;
int i = 0;
mutex_lock(&adc->lock);
for_each_set_bit(scan_index, indio_dev->active_scan_mask,
indio_dev->masklength) {
const struct iio_chan_spec *scan_chan =
&indio_dev->channels[scan_index];
int ret = max1118_read(adc->spi, scan_chan->channel);
if (ret < 0) {
dev_warn(&adc->spi->dev,
"failed to get conversion data\n");
goto out;
}
data[i] = ret;
i++;
}
iio_push_to_buffers_with_timestamp(indio_dev, data,
iio_get_time_ns(indio_dev));
out:
mutex_unlock(&adc->lock);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
static int max1118_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct max1118 *adc;
const struct spi_device_id *id = spi_get_device_id(spi);
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
if (!indio_dev)
return -ENOMEM;
adc = iio_priv(indio_dev);
adc->spi = spi;
mutex_init(&adc->lock);
if (id->driver_data == max1118) {
adc->reg = devm_regulator_get(&spi->dev, "vref");
if (IS_ERR(adc->reg)) {
dev_err(&spi->dev, "failed to get vref regulator\n");
return PTR_ERR(adc->reg);
}
ret = regulator_enable(adc->reg);
if (ret)
return ret;
}
spi_set_drvdata(spi, indio_dev);
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &max1118_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = max1118_channels;
indio_dev->num_channels = ARRAY_SIZE(max1118_channels);
/*
* To reinitiate a conversion on CH0, it is necessary to allow for a
* conversion to be complete and all of the data to be read out. Once
* a conversion has been completed, the MAX1117/MAX1118/MAX1119 will go
* into AutoShutdown mode until the next conversion is initiated.
*/
max1118_read(spi, 0);
ret = iio_triggered_buffer_setup(indio_dev, NULL,
max1118_trigger_handler, NULL);
if (ret)
goto err_reg_disable;
ret = iio_device_register(indio_dev);
if (ret)
goto err_buffer_cleanup;
return 0;
err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
err_reg_disable:
if (id->driver_data == max1118)
regulator_disable(adc->reg);
return ret;
}
static int max1118_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct max1118 *adc = iio_priv(indio_dev);
const struct spi_device_id *id = spi_get_device_id(spi);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
if (id->driver_data == max1118)
return regulator_disable(adc->reg);
return 0;
}
static const struct spi_device_id max1118_id[] = {
{ "max1117", max1117 },
{ "max1118", max1118 },
{ "max1119", max1119 },
{}
};
MODULE_DEVICE_TABLE(spi, max1118_id);
#ifdef CONFIG_OF
static const struct of_device_id max1118_dt_ids[] = {
{ .compatible = "maxim,max1117" },
{ .compatible = "maxim,max1118" },
{ .compatible = "maxim,max1119" },
{},
};
MODULE_DEVICE_TABLE(of, max1118_dt_ids);
#endif
static struct spi_driver max1118_spi_driver = {
.driver = {
.name = "max1118",
.of_match_table = of_match_ptr(max1118_dt_ids),
},
.probe = max1118_probe,
.remove = max1118_remove,
.id_table = max1118_id,
};
module_spi_driver(max1118_spi_driver);
MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
MODULE_DESCRIPTION("MAXIM MAX1117/MAX1118/MAX1119 ADCs driver");
MODULE_LICENSE("GPL v2");
......@@ -1007,7 +1007,7 @@ static struct attribute *max1363_event_attributes[] = {
NULL,
};
static struct attribute_group max1363_event_attribute_group = {
static const struct attribute_group max1363_event_attribute_group = {
.attrs = max1363_event_attributes,
};
......
This diff is collapsed.
......@@ -18,7 +18,9 @@
#include <linux/io.h>
#include <linux/iio/iio.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
......@@ -163,6 +165,9 @@
#define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8)
#define MESON_SAR_ADC_MAX_FIFO_SIZE 32
#define MESON_SAR_ADC_TIMEOUT 100 /* ms */
/* for use with IIO_VAL_INT_PLUS_MICRO */
#define MILLION 1000000
#define MESON_SAR_ADC_CHAN(_chan) { \
.type = IIO_VOLTAGE, \
......@@ -170,7 +175,9 @@
.channel = _chan, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_AVERAGE_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_CALIBBIAS) | \
BIT(IIO_CHAN_INFO_CALIBSCALE), \
.datasheet_name = "SAR_ADC_CH"#_chan, \
}
......@@ -229,6 +236,9 @@ struct meson_sar_adc_priv {
struct clk_gate clk_gate;
struct clk *adc_div_clk;
struct clk_divider clk_div;
struct completion done;
int calibbias;
int calibscale;
};
static const struct regmap_config meson_sar_adc_regmap_config = {
......@@ -248,6 +258,17 @@ static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev)
return FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
}
static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
int tmp;
/* use val_calib = scale * val_raw + offset calibration function */
tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias;
return clamp(tmp, 0, (1 << priv->data->resolution) - 1);
}
static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
......@@ -274,33 +295,31 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
int *val)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
int ret, regval, fifo_chan, fifo_val, sum = 0, count = 0;
int regval, fifo_chan, fifo_val, count;
ret = meson_sar_adc_wait_busy_clear(indio_dev);
if (ret)
return ret;
while (meson_sar_adc_get_fifo_count(indio_dev) > 0 &&
count < MESON_SAR_ADC_MAX_FIFO_SIZE) {
regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &regval);
fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK,
regval);
if (fifo_chan != chan->channel)
continue;
fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK,
regval);
fifo_val &= (BIT(priv->data->resolution) - 1);
if(!wait_for_completion_timeout(&priv->done,
msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT)))
return -ETIMEDOUT;
sum += fifo_val;
count++;
count = meson_sar_adc_get_fifo_count(indio_dev);
if (count != 1) {
dev_err(&indio_dev->dev,
"ADC FIFO has %d element(s) instead of one\n", count);
return -EINVAL;
}
if (!count)
return -ENOENT;
regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &regval);
fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval);
if (fifo_chan != chan->channel) {
dev_err(&indio_dev->dev,
"ADC FIFO entry belongs to channel %d instead of %d\n",
fifo_chan, chan->channel);
return -EINVAL;
}
*val = sum / count;
fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval);
fifo_val &= GENMASK(priv->data->resolution - 1, 0);
*val = meson_sar_adc_calib_val(indio_dev, fifo_val);
return 0;
}
......@@ -378,6 +397,12 @@ static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
reinit_completion(&priv->done);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_FIFO_IRQ_EN,
MESON_SAR_ADC_REG0_FIFO_IRQ_EN);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE,
MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
......@@ -391,6 +416,9 @@ static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_SAMPLING_STOP,
MESON_SAR_ADC_REG0_SAMPLING_STOP);
......@@ -516,6 +544,15 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev,
*val2 = priv->data->resolution;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_CALIBBIAS:
*val = priv->calibbias;
return IIO_VAL_INT;
case IIO_CHAN_INFO_CALIBSCALE:
*val = priv->calibscale / MILLION;
*val2 = priv->calibscale % MILLION;
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
......@@ -643,6 +680,7 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
int ret;
u32 regval;
ret = meson_sar_adc_lock(indio_dev);
if (ret)
......@@ -667,6 +705,9 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
goto err_sana_clk;
}
regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
MESON_SAR_ADC_REG11_BANDGAP_EN,
MESON_SAR_ADC_REG11_BANDGAP_EN);
......@@ -728,6 +769,66 @@ static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
return 0;
}
static irqreturn_t meson_sar_adc_irq(int irq, void *data)
{
struct iio_dev *indio_dev = data;
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
unsigned int cnt, threshold;
u32 regval;
regmap_read(priv->regmap, MESON_SAR_ADC_REG0, &regval);
cnt = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
threshold = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
if (cnt < threshold)
return IRQ_NONE;
complete(&priv->done);
return IRQ_HANDLED;
}
static int meson_sar_adc_calib(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
int ret, nominal0, nominal1, value0, value1;
/* use points 25% and 75% for calibration */
nominal0 = (1 << priv->data->resolution) / 4;
nominal1 = (1 << priv->data->resolution) * 3 / 4;
meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4);
usleep_range(10, 20);
ret = meson_sar_adc_get_sample(indio_dev,
&meson_sar_adc_iio_channels[7],
MEAN_AVERAGING, EIGHT_SAMPLES, &value0);
if (ret < 0)
goto out;
meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4);
usleep_range(10, 20);
ret = meson_sar_adc_get_sample(indio_dev,
&meson_sar_adc_iio_channels[7],
MEAN_AVERAGING, EIGHT_SAMPLES, &value1);
if (ret < 0)
goto out;
if (value1 <= value0) {
ret = -EINVAL;
goto out;
}
priv->calibscale = div_s64((nominal1 - nominal0) * (s64)MILLION,
value1 - value0);
priv->calibbias = nominal0 - div_s64((s64)value0 * priv->calibscale,
MILLION);
ret = 0;
out:
meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT);
return ret;
}
static const struct iio_info meson_sar_adc_iio_info = {
.read_raw = meson_sar_adc_iio_info_read_raw,
.driver_module = THIS_MODULE,
......@@ -770,7 +871,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
struct resource *res;
void __iomem *base;
const struct of_device_id *match;
int ret;
int irq, ret;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
if (!indio_dev) {
......@@ -779,6 +880,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
}
priv = iio_priv(indio_dev);
init_completion(&priv->done);
match = of_match_device(meson_sar_adc_of_match, &pdev->dev);
priv->data = match->data;
......@@ -797,6 +899,15 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
if (!irq)
return -EINVAL;
ret = devm_request_irq(&pdev->dev, irq, meson_sar_adc_irq, IRQF_SHARED,
dev_name(&pdev->dev), indio_dev);
if (ret)
return ret;
priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
&meson_sar_adc_regmap_config);
if (IS_ERR(priv->regmap))
......@@ -857,6 +968,8 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
return PTR_ERR(priv->vref);
}
priv->calibscale = MILLION;
ret = meson_sar_adc_init(indio_dev);
if (ret)
goto err;
......@@ -865,6 +978,10 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
if (ret)
goto err;
ret = meson_sar_adc_calib(indio_dev);
if (ret)
dev_warn(&pdev->dev, "calibration failed\n");
platform_set_drvdata(pdev, indio_dev);
ret = iio_device_register(indio_dev);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment