You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'iio-for-3.20b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-testing
Jonathan writes: Second round of IIO new drivers, functionality and cleanups for the 3.20 cycle. New drivers and device support: * Capella cm3232 ambient light sensor driver. * Freescale MMA9553 pedometer and activity monitor. Note this involved a refactor of the mma9551 driver to pull out shared elements. * Samsung sensor hub (as used in the galaxy gear 2 watch) Core support and initial drivers (gyro and accelerometer) more to follow. An additional fix was applied on top of this for a build issue thrown up by the autobuilders on some platforms. * Cosmic Circuits 10001 ADC driver * Qualcomm SPMI PMIC voltage ADC driver (current adc merged a while back). * Add binding for AK8963 (in capitals) as unfortunately there are bios' out there not using lower case. New functionality * Add newe operating mode to the core to allow for non triggered software buffers. This is mostly semantics as previously drivers just claimed they had a hardware buffer (when they didn't). * Add distance channel type. * Add energy channel type. * Add velocity channel type and IIO_MOD_ROOT_SUM_SQUARED (i.e. speed when our channel type is velocity). * Add _debounce_count and _debounce_time filter attributes. Only really make sense for counting types of measurements. First use is for avoiding miss detection of steps prior to walking. * Add change event type. This replaces the briefly present INSTANCE type (which hadn't gained any users). It is more generic as it allows for events say every 10 steps rather than every step. * Add _calibweight attributes to the ABI (and core support). Used by activity monitors to estimate energy use. Can imagine there will be other uses for this one. Driver new functionality * mma9551 gains runtime pm support. * hid-sensors gain PM support. Cleanup * Change calibheight unit to m from cm. As there are no prior users and this was inconsistent with other distance units, it makes sense to fix it before hte mma9553 driver which uses it. * mpu6050 cleanups and devm_ use. * as3935 switch over to PM ops. * Fix a few format strings for signed vs unsigned. * Fix tcs3414 missindentation * Typo in industrialio-event * Stop requiring IIO_TRIGGER for IIO_KFIFO_BUF as we have drivers that don't need it. No one is quite sure why that dependency was there and it seems to not matter.
This commit is contained in:
@@ -282,6 +282,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_current_scale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_peak_scale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_scale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_energy_scale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_distance_scale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_scale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_x_scale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_y_scale
|
||||
@@ -293,6 +295,7 @@ What: /sys/bus/iio/devices/iio:deviceX/in_rot_from_north_true_tilt_comp_scale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_scale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressure_scale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_humidityrelative_scale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_scale
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
@@ -340,14 +343,44 @@ Description:
|
||||
production inaccuracies). If shared across all channels,
|
||||
<type>_calibscale is used.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_steps_calibheight
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_activity_calibgender
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_energy_calibgender
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_distance_calibgender
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_velocity_calibgender
|
||||
KernelVersion: 3.20
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Gender of the user (e.g.: male, female) used by some pedometers
|
||||
to compute the stride length, distance, speed and activity
|
||||
type.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_activity_calibgender_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_energy_calibgender_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_distance_calibgender_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_velocity_calibgender_available
|
||||
KernelVersion: 3.20
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Lists all available gender values (e.g.: male, female).
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_activity_calibheight
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_energy_calibheight
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_distance_calibheight
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_velocity_calibheight
|
||||
KernelVersion: 3.19
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Height of the user (in centimeters) used by some pedometers
|
||||
Height of the user (in meters) used by some pedometers
|
||||
to compute the stride length, distance, speed and activity
|
||||
type.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_energy_calibweight
|
||||
KernelVersion: 3.20
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Weight of the user (in kg). It is needed by some pedometers
|
||||
to compute the calories burnt by the user.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale_available
|
||||
What: /sys/.../iio:deviceX/in_voltageX_scale_available
|
||||
What: /sys/.../iio:deviceX/in_voltage-voltage_scale_available
|
||||
@@ -808,6 +841,14 @@ What: /sys/.../events/in_tempY_roc_falling_period
|
||||
What: /sys/.../events/in_accel_x&y&z_mag_falling_period
|
||||
What: /sys/.../events/in_intensity0_thresh_period
|
||||
What: /sys/.../events/in_proximity0_thresh_period
|
||||
What: /sys/.../events/in_activity_still_thresh_rising_period
|
||||
What: /sys/.../events/in_activity_still_thresh_falling_period
|
||||
What: /sys/.../events/in_activity_walking_thresh_rising_period
|
||||
What: /sys/.../events/in_activity_walking_thresh_falling_period
|
||||
What: /sys/.../events/in_activity_jogging_thresh_rising_period
|
||||
What: /sys/.../events/in_activity_jogging_thresh_falling_period
|
||||
What: /sys/.../events/in_activity_running_thresh_rising_period
|
||||
What: /sys/.../events/in_activity_running_thresh_falling_period
|
||||
KernelVersion: 2.6.37
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
@@ -881,12 +922,24 @@ Description:
|
||||
number or direction is not specified, applies to all channels of
|
||||
this type.
|
||||
|
||||
What: /sys/.../events/in_steps_instance_en
|
||||
KernelVersion: 3.19
|
||||
What: /sys/.../events/in_steps_change_en
|
||||
KernelVersion: 3.20
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Enables or disables step detection. Each time the user takes a step an
|
||||
event of this type will be generated.
|
||||
Event generated when channel passes a threshold on the absolute
|
||||
change in value. E.g. for steps: a step change event is
|
||||
generated each time the user takes N steps, where N is set using
|
||||
in_steps_change_value.
|
||||
|
||||
What: /sys/.../events/in_steps_change_value
|
||||
KernelVersion: 3.20
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Specifies the value of change threshold that the
|
||||
device is comparing against for the events enabled by
|
||||
<type>[Y][_name]_roc[_rising|falling|]_en. E.g. for steps:
|
||||
if set to 3, a step change event will be generated every 3
|
||||
steps.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/trigger/current_trigger
|
||||
KernelVersion: 2.6.35
|
||||
@@ -1049,6 +1102,24 @@ Description:
|
||||
For a list of available output power modes read
|
||||
in_accel_power_mode_available.
|
||||
|
||||
What: /sys/.../iio:deviceX/in_energy_input
|
||||
What: /sys/.../iio:deviceX/in_energy_raw
|
||||
KernelVersion: 3.20
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
This attribute is used to read the energy value reported by the
|
||||
device (e.g.: human activity sensors report energy burnt by the
|
||||
user). Units after application of scale are Joules.
|
||||
|
||||
What: /sys/.../iio:deviceX/in_distance_input
|
||||
What: /sys/.../iio:deviceX/in_distance_raw
|
||||
KernelVersion: 3.20
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
This attribute is used to read the distance covered by the user
|
||||
since the last reboot while activated. Units after application
|
||||
of scale are meters.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/store_eeprom
|
||||
KernelVersion: 3.4.0
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
@@ -1102,6 +1173,12 @@ Description:
|
||||
This attribute is used to get/set the integration time in
|
||||
seconds.
|
||||
|
||||
What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_integration_time
|
||||
KernelVersion: 3.20
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Number of seconds in which to compute speed.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_rot_quaternion_raw
|
||||
KernelVersion: 3.15
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
@@ -1130,13 +1207,17 @@ Description:
|
||||
present, output should be considered as processed with the
|
||||
unit in milliamps.
|
||||
|
||||
What: /sys/.../iio:deviceX/in_energy_en
|
||||
What: /sys/.../iio:deviceX/in_distance_en
|
||||
What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_en
|
||||
What: /sys/.../iio:deviceX/in_steps_en
|
||||
KernelVersion: 3.19
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Activates the step counter. After activation, the number of steps
|
||||
taken by the user will be counted in hardware and exported through
|
||||
in_steps_input.
|
||||
Activates a device feature that runs in firmware/hardware.
|
||||
E.g. for steps: the pedometer saves power while not used;
|
||||
when activated, it will count the steps taken by the user in
|
||||
firmware and export them through in_steps_input.
|
||||
|
||||
What: /sys/.../iio:deviceX/in_steps_input
|
||||
KernelVersion: 3.19
|
||||
@@ -1144,3 +1225,27 @@ Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
This attribute is used to read the number of steps taken by the user
|
||||
since the last reboot while activated.
|
||||
|
||||
What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_input
|
||||
What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_raw
|
||||
KernelVersion: 3.19
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
This attribute is used to read the current speed value of the
|
||||
user (which is the norm or magnitude of the velocity vector).
|
||||
Units after application of scale are m/s.
|
||||
|
||||
What: /sys/.../iio:deviceX/in_steps_debounce_count
|
||||
KernelVersion: 3.20
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Specifies the number of steps that must occur within
|
||||
in_steps_filter_debounce_time for the pedometer to decide the
|
||||
consumer is making steps.
|
||||
|
||||
What: /sys/.../iio:deviceX/in_steps_debounce_time
|
||||
KernelVersion: 3.20
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Specifies number of seconds in which we compute the steps
|
||||
that occur in order to decide if the consumer is making steps.
|
||||
|
||||
@@ -34,6 +34,7 @@ atmel,24c512 i2c serial eeprom (24cxx)
|
||||
atmel,24c1024 i2c serial eeprom (24cxx)
|
||||
atmel,at97sc3204t i2c trusted platform module (TPM)
|
||||
capella,cm32181 CM32181: Ambient Light Sensor
|
||||
capella,cm3232 CM3232: Ambient Light Sensor
|
||||
catalyst,24c32 i2c serial eeprom
|
||||
cirrus,cs42l51 Cirrus Logic CS42L51 audio codec
|
||||
dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
* Cosmic Circuits - Analog to Digital Converter (CC-10001-ADC)
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "cosmic,10001-adc"
|
||||
- reg: Should contain adc registers location and length.
|
||||
- clock-names: Should contain "adc".
|
||||
- clocks: Should contain a clock specifier for each entry in clock-names
|
||||
- vref-supply: The regulator supply ADC reference voltage.
|
||||
|
||||
Optional properties:
|
||||
- adc-reserved-channels: Bitmask of reserved channels,
|
||||
i.e. channels that cannot be used by the OS.
|
||||
|
||||
Example:
|
||||
adc: adc@18101600 {
|
||||
compatible = "cosmic,10001-adc";
|
||||
reg = <0x18101600 0x24>;
|
||||
adc-reserved-channels = <0x2>;
|
||||
clocks = <&adc_clk>;
|
||||
clock-names = "adc";
|
||||
vref-supply = <®_1v8>;
|
||||
};
|
||||
@@ -0,0 +1,129 @@
|
||||
Qualcomm's SPMI PMIC voltage ADC
|
||||
|
||||
SPMI PMIC voltage ADC (VADC) provides interface to clients to read
|
||||
voltage. The VADC is a 15-bit sigma-delta ADC.
|
||||
|
||||
VADC node:
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: Should contain "qcom,spmi-vadc".
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: VADC base address and length in the SPMI PMIC register map.
|
||||
|
||||
- #address-cells:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: Must be one. Child node 'reg' property should define ADC
|
||||
channel number.
|
||||
|
||||
- #size-cells:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: Must be zero.
|
||||
|
||||
- #io-channel-cells:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: Must be one. For details about IIO bindings see:
|
||||
Documentation/devicetree/bindings/iio/iio-bindings.txt
|
||||
|
||||
- interrupts:
|
||||
Usage: optional
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: End of conversion interrupt.
|
||||
|
||||
Channel node properties:
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: ADC channel number.
|
||||
See include/dt-bindings/iio/qcom,spmi-vadc.h
|
||||
|
||||
- qcom,decimation:
|
||||
Usage: optional
|
||||
Value type: <u32>
|
||||
Definition: This parameter is used to decrease ADC sampling rate.
|
||||
Quicker measurements can be made by reducing decimation ratio.
|
||||
Valid values are 512, 1024, 2048, 4096.
|
||||
If property is not found, default value of 512 will be used.
|
||||
|
||||
- qcom,pre-scaling:
|
||||
Usage: optional
|
||||
Value type: <u32 array>
|
||||
Definition: Used for scaling the channel input signal before the signal is
|
||||
fed to VADC. The configuration for this node is to know the
|
||||
pre-determined ratio and use it for post scaling. Select one from
|
||||
the following options.
|
||||
<1 1>, <1 3>, <1 4>, <1 6>, <1 20>, <1 8>, <10 81>, <1 10>
|
||||
If property is not found default value depending on chip will be used.
|
||||
|
||||
- qcom,ratiometric:
|
||||
Usage: optional
|
||||
Value type: <empty>
|
||||
Definition: Channel calibration type. If this property is specified
|
||||
VADC will use the VDD reference (1.8V) and GND for channel
|
||||
calibration. If property is not found, channel will be
|
||||
calibrated with 0.625V and 1.25V reference channels, also
|
||||
known as absolute calibration.
|
||||
|
||||
- qcom,hw-settle-time:
|
||||
Usage: optional
|
||||
Value type: <u32>
|
||||
Definition: Time between AMUX getting configured and the ADC starting
|
||||
conversion. Delay = 100us * (value) for value < 11, and
|
||||
2ms * (value - 10) otherwise.
|
||||
Valid values are: 0, 100, 200, 300, 400, 500, 600, 700, 800,
|
||||
900 us and 1, 2, 4, 6, 8, 10 ms
|
||||
If property is not found, channel will use 0us.
|
||||
|
||||
- qcom,avg-samples:
|
||||
Usage: optional
|
||||
Value type: <u32>
|
||||
Definition: Number of samples to be used for measurement.
|
||||
Averaging provides the option to obtain a single measurement
|
||||
from the ADC that is an average of multiple samples. The value
|
||||
selected is 2^(value).
|
||||
Valid values are: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512
|
||||
If property is not found, 1 sample will be used.
|
||||
|
||||
NOTE:
|
||||
|
||||
Following channels, also known as reference point channels, are used for
|
||||
result calibration and their channel configuration nodes should be defined:
|
||||
VADC_REF_625MV and/or VADC_SPARE1(based on PMIC version) VADC_REF_1250MV,
|
||||
VADC_GND_REF and VADC_VDD_VADC.
|
||||
|
||||
Example:
|
||||
|
||||
/* VADC node */
|
||||
pmic_vadc: vadc@3100 {
|
||||
compatible = "qcom,spmi-vadc";
|
||||
reg = <0x3100 0x100>;
|
||||
interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#io-channel-cells = <1>;
|
||||
io-channel-ranges;
|
||||
|
||||
/* Channel node */
|
||||
usb_id_nopull {
|
||||
reg = <VADC_LR_MUX10_USB_ID>;
|
||||
qcom,decimation = <512>;
|
||||
qcom,ratiometric;
|
||||
qcom,hw-settle-time = <200>;
|
||||
qcom,avg-samples = <1>;
|
||||
qcom,pre-scaling = <1 3>;
|
||||
};
|
||||
};
|
||||
|
||||
/* IIO client node */
|
||||
usb {
|
||||
io-channels = <&pmic_vadc VADC_LR_MUX10_USB_ID>;
|
||||
io-channel-names = "vadc";
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
Samsung Sensorhub driver
|
||||
|
||||
Sensorhub is a MCU which manages several sensors and also plays the role
|
||||
of a virtual sensor device.
|
||||
|
||||
Required properties:
|
||||
- compatible: "samsung,sensorhub-rinato" or "samsung,sensorhub-thermostat"
|
||||
- spi-max-frequency: max SPI clock frequency
|
||||
- interrupt-parent: interrupt parent
|
||||
- interrupts: communication interrupt
|
||||
- ap-mcu-gpios: [out] ap to sensorhub line - used during communication
|
||||
- mcu-ap-gpios: [in] sensorhub to ap - used during communication
|
||||
- mcu-reset-gpios: [out] sensorhub reset
|
||||
|
||||
Example:
|
||||
|
||||
shub_spi: shub {
|
||||
compatible = "samsung,sensorhub-rinato";
|
||||
spi-max-frequency = <5000000>;
|
||||
interrupt-parent = <&gpx0>;
|
||||
interrupts = <2 0>;
|
||||
ap-mcu-gpios = <&gpx0 0 0>;
|
||||
mcu-ap-gpios = <&gpx0 4 0>;
|
||||
mcu-reset-gpios = <&gpx0 5 0>;
|
||||
};
|
||||
@@ -36,6 +36,7 @@ chunghwa Chunghwa Picture Tubes Ltd.
|
||||
cirrus Cirrus Logic, Inc.
|
||||
cnm Chips&Media, Inc.
|
||||
cortina Cortina Systems, Inc.
|
||||
cosmic Cosmic Circuits
|
||||
crystalfontz Crystalfontz America, Inc.
|
||||
dallas Maxim Integrated Products (formerly Dallas Semiconductor)
|
||||
davicom DAVICOM Semiconductor, Inc.
|
||||
|
||||
@@ -2379,6 +2379,12 @@ F: security/capability.c
|
||||
F: security/commoncap.c
|
||||
F: kernel/capability.c
|
||||
|
||||
CAPELLA MICROSYSTEMS LIGHT SENSOR DRIVER
|
||||
M: Kevin Tsai <ktsai@capellamicro.com>
|
||||
S: Maintained
|
||||
F: drivers/iio/light/cm*
|
||||
F: Documentation/devicetree/bindings/i2c/trivial-devices.txt
|
||||
|
||||
CC2520 IEEE-802.15.4 RADIO DRIVER
|
||||
M: Varka Bhadram <varkabhadram@gmail.com>
|
||||
L: linux-wpan@vger.kernel.org
|
||||
|
||||
@@ -27,7 +27,6 @@ boolean "IIO callback buffer used for push in-kernel interfaces"
|
||||
usage. That is, those where the data is pushed to the consumer.
|
||||
|
||||
config IIO_KFIFO_BUF
|
||||
select IIO_TRIGGER
|
||||
tristate "Industrial I/O buffering based on kfifo"
|
||||
help
|
||||
A simple fifo based on kfifo. Note that this currently provides
|
||||
|
||||
@@ -111,9 +111,14 @@ config KXCJK1013
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called kxcjk-1013.
|
||||
|
||||
config MMA9551_CORE
|
||||
tristate
|
||||
|
||||
config MMA9551
|
||||
tristate "Freescale MMA9551L Intelligent Motion-Sensing Platform Driver"
|
||||
depends on I2C
|
||||
select MMA9551_CORE
|
||||
|
||||
help
|
||||
Say yes here to build support for the Freescale MMA9551L
|
||||
Intelligent Motion-Sensing Platform Driver.
|
||||
@@ -121,4 +126,14 @@ config MMA9551
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called mma9551.
|
||||
|
||||
config MMA9553
|
||||
tristate "Freescale MMA9553L Intelligent Pedometer Platform Driver"
|
||||
depends on I2C
|
||||
select MMA9551_CORE
|
||||
help
|
||||
Say yes here to build support for the Freescale MMA9553L
|
||||
Intelligent Pedometer Platform Driver.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called mma9553.
|
||||
endmenu
|
||||
|
||||
@@ -9,7 +9,12 @@ obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
|
||||
obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
|
||||
obj-$(CONFIG_KXSD9) += kxsd9.o
|
||||
obj-$(CONFIG_MMA8452) += mma8452.o
|
||||
obj-$(CONFIG_MMA9551) += mma9551.o
|
||||
|
||||
obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o
|
||||
obj-$(CONFIG_MMA9551) += mma9551.o
|
||||
obj-$(CONFIG_MMA9553) += mma9553.o
|
||||
|
||||
obj-$(CONFIG_IIO_SSP_SENSORS_COMMONS) += ssp_accel_sensor.o
|
||||
|
||||
obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o
|
||||
st_accel-y := st_accel_core.o
|
||||
|
||||
@@ -111,19 +111,12 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
|
||||
int report_id = -1;
|
||||
u32 address;
|
||||
int ret_type;
|
||||
s32 poll_value;
|
||||
|
||||
*val = 0;
|
||||
*val2 = 0;
|
||||
switch (mask) {
|
||||
case 0:
|
||||
poll_value = hid_sensor_read_poll_value(
|
||||
&accel_state->common_attributes);
|
||||
if (poll_value < 0)
|
||||
return -EINVAL;
|
||||
|
||||
hid_sensor_power_state(&accel_state->common_attributes, true);
|
||||
msleep_interruptible(poll_value * 2);
|
||||
report_id = accel_state->accel[chan->scan_index].report_id;
|
||||
address = accel_3d_addresses[chan->scan_index];
|
||||
if (report_id >= 0)
|
||||
@@ -419,6 +412,7 @@ static struct platform_driver hid_accel_3d_platform_driver = {
|
||||
.id_table = hid_accel_3d_ids,
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.pm = &hid_sensor_pm_ops,
|
||||
},
|
||||
.probe = hid_accel_3d_probe,
|
||||
.remove = hid_accel_3d_remove,
|
||||
|
||||
+86
-405
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Common code for Freescale MMA955x Intelligent Sensor Platform drivers
|
||||
* Copyright (c) 2014, Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#ifndef _MMA9551_CORE_H_
|
||||
#define _MMA9551_CORE_H_
|
||||
|
||||
/* Applications IDs */
|
||||
#define MMA9551_APPID_VERSION 0x00
|
||||
#define MMA9551_APPID_GPIO 0x03
|
||||
#define MMA9551_APPID_AFE 0x06
|
||||
#define MMA9551_APPID_TILT 0x0B
|
||||
#define MMA9551_APPID_SLEEP_WAKE 0x12
|
||||
#define MMA9551_APPID_PEDOMETER 0x15
|
||||
#define MMA9551_APPID_RCS 0x17
|
||||
#define MMA9551_APPID_NONE 0xff
|
||||
|
||||
/* Reset/Suspend/Clear application app masks */
|
||||
#define MMA9551_RSC_PED BIT(21)
|
||||
|
||||
#define MMA9551_AUTO_SUSPEND_DELAY_MS 2000
|
||||
|
||||
enum mma9551_gpio_pin {
|
||||
mma9551_gpio6 = 0,
|
||||
mma9551_gpio7,
|
||||
mma9551_gpio8,
|
||||
mma9551_gpio9,
|
||||
mma9551_gpio_max = mma9551_gpio9,
|
||||
};
|
||||
|
||||
#define MMA9551_ACCEL_CHANNEL(axis) { \
|
||||
.type = IIO_ACCEL, \
|
||||
.modified = 1, \
|
||||
.channel2 = axis, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
||||
}
|
||||
|
||||
int mma9551_read_config_byte(struct i2c_client *client, u8 app_id,
|
||||
u16 reg, u8 *val);
|
||||
int mma9551_write_config_byte(struct i2c_client *client, u8 app_id,
|
||||
u16 reg, u8 val);
|
||||
int mma9551_read_status_byte(struct i2c_client *client, u8 app_id,
|
||||
u16 reg, u8 *val);
|
||||
int mma9551_read_config_word(struct i2c_client *client, u8 app_id,
|
||||
u16 reg, u16 *val);
|
||||
int mma9551_write_config_word(struct i2c_client *client, u8 app_id,
|
||||
u16 reg, u16 val);
|
||||
int mma9551_read_status_word(struct i2c_client *client, u8 app_id,
|
||||
u16 reg, u16 *val);
|
||||
int mma9551_read_config_words(struct i2c_client *client, u8 app_id,
|
||||
u16 reg, u8 len, u16 *buf);
|
||||
int mma9551_read_status_words(struct i2c_client *client, u8 app_id,
|
||||
u16 reg, u8 len, u16 *buf);
|
||||
int mma9551_write_config_words(struct i2c_client *client, u8 app_id,
|
||||
u16 reg, u8 len, u16 *buf);
|
||||
int mma9551_update_config_bits(struct i2c_client *client, u8 app_id,
|
||||
u16 reg, u8 mask, u8 val);
|
||||
int mma9551_gpio_config(struct i2c_client *client, enum mma9551_gpio_pin pin,
|
||||
u8 app_id, u8 bitnum, int polarity);
|
||||
int mma9551_read_version(struct i2c_client *client);
|
||||
int mma9551_set_device_state(struct i2c_client *client, bool enable);
|
||||
int mma9551_set_power_state(struct i2c_client *client, bool on);
|
||||
void mma9551_sleep(int freq);
|
||||
int mma9551_read_accel_chan(struct i2c_client *client,
|
||||
const struct iio_chan_spec *chan,
|
||||
int *val, int *val2);
|
||||
int mma9551_read_accel_scale(int *val, int *val2);
|
||||
int mma9551_app_reset(struct i2c_client *client, u32 app_mask);
|
||||
|
||||
#endif /* _MMA9551_CORE_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/iio/common/ssp_sensors.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/kfifo_buf.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include "../common/ssp_sensors/ssp_iio_sensor.h"
|
||||
|
||||
#define SSP_CHANNEL_COUNT 3
|
||||
|
||||
#define SSP_ACCEL_NAME "ssp-accelerometer"
|
||||
static const char ssp_accel_device_name[] = SSP_ACCEL_NAME;
|
||||
|
||||
enum ssp_accel_3d_channel {
|
||||
SSP_CHANNEL_SCAN_INDEX_X,
|
||||
SSP_CHANNEL_SCAN_INDEX_Y,
|
||||
SSP_CHANNEL_SCAN_INDEX_Z,
|
||||
SSP_CHANNEL_SCAN_INDEX_TIME,
|
||||
};
|
||||
|
||||
static int ssp_accel_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan, int *val,
|
||||
int *val2, long mask)
|
||||
{
|
||||
u32 t;
|
||||
struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent);
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
t = ssp_get_sensor_delay(data, SSP_ACCELEROMETER_SENSOR);
|
||||
ssp_convert_to_freq(t, val, val2);
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ssp_accel_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan, int val,
|
||||
int val2, long mask)
|
||||
{
|
||||
int ret;
|
||||
struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent);
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
ret = ssp_convert_to_time(val, val2);
|
||||
ret = ssp_change_delay(data, SSP_ACCELEROMETER_SENSOR, ret);
|
||||
if (ret < 0)
|
||||
dev_err(&indio_dev->dev, "accel sensor enable fail\n");
|
||||
|
||||
return ret;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct iio_info ssp_accel_iio_info = {
|
||||
.read_raw = &ssp_accel_read_raw,
|
||||
.write_raw = &ssp_accel_write_raw,
|
||||
};
|
||||
|
||||
static const unsigned long ssp_accel_scan_mask[] = { 0x7, 0, };
|
||||
|
||||
static const struct iio_chan_spec ssp_acc_channels[] = {
|
||||
SSP_CHANNEL_AG(IIO_ACCEL, IIO_MOD_X, SSP_CHANNEL_SCAN_INDEX_X),
|
||||
SSP_CHANNEL_AG(IIO_ACCEL, IIO_MOD_Y, SSP_CHANNEL_SCAN_INDEX_Y),
|
||||
SSP_CHANNEL_AG(IIO_ACCEL, IIO_MOD_Z, SSP_CHANNEL_SCAN_INDEX_Z),
|
||||
SSP_CHAN_TIMESTAMP(SSP_CHANNEL_SCAN_INDEX_TIME),
|
||||
};
|
||||
|
||||
static int ssp_process_accel_data(struct iio_dev *indio_dev, void *buf,
|
||||
int64_t timestamp)
|
||||
{
|
||||
return ssp_common_process_data(indio_dev, buf, SSP_ACCELEROMETER_SIZE,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
static const struct iio_buffer_setup_ops ssp_accel_buffer_ops = {
|
||||
.postenable = &ssp_common_buffer_postenable,
|
||||
.postdisable = &ssp_common_buffer_postdisable,
|
||||
};
|
||||
|
||||
static int ssp_accel_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct iio_dev *indio_dev;
|
||||
struct ssp_sensor_data *spd;
|
||||
struct iio_buffer *buffer;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*spd));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
spd = iio_priv(indio_dev);
|
||||
|
||||
spd->process_data = ssp_process_accel_data;
|
||||
spd->type = SSP_ACCELEROMETER_SENSOR;
|
||||
|
||||
indio_dev->name = ssp_accel_device_name;
|
||||
indio_dev->dev.parent = &pdev->dev;
|
||||
indio_dev->dev.of_node = pdev->dev.of_node;
|
||||
indio_dev->info = &ssp_accel_iio_info;
|
||||
indio_dev->modes = INDIO_BUFFER_SOFTWARE;
|
||||
indio_dev->channels = ssp_acc_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(ssp_acc_channels);
|
||||
indio_dev->available_scan_masks = ssp_accel_scan_mask;
|
||||
|
||||
buffer = devm_iio_kfifo_allocate(&pdev->dev);
|
||||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
iio_device_attach_buffer(indio_dev, buffer);
|
||||
|
||||
indio_dev->setup_ops = &ssp_accel_buffer_ops;
|
||||
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* ssp registering should be done after all iio setup */
|
||||
ssp_register_consumer(indio_dev, SSP_ACCELEROMETER_SENSOR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssp_accel_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ssp_accel_driver = {
|
||||
.driver = {
|
||||
.name = SSP_ACCEL_NAME,
|
||||
},
|
||||
.probe = ssp_accel_probe,
|
||||
.remove = ssp_accel_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(ssp_accel_driver);
|
||||
|
||||
MODULE_AUTHOR("Karol Wrona <k.wrona@samsung.com>");
|
||||
MODULE_DESCRIPTION("Samsung sensorhub accelerometers driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -135,6 +135,17 @@ config AXP288_ADC
|
||||
device. Depending on platform configuration, this general purpose ADC can
|
||||
be used for sampling sensors such as thermal resistors.
|
||||
|
||||
config CC10001_ADC
|
||||
tristate "Cosmic Circuits 10001 ADC driver"
|
||||
depends on HAS_IOMEM || HAVE_CLK || REGULATOR
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
Say yes here to build support for Cosmic Circuits 10001 ADC.
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called cc10001_adc.
|
||||
|
||||
config EXYNOS_ADC
|
||||
tristate "Exynos ADC driver support"
|
||||
depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST)
|
||||
@@ -228,6 +239,20 @@ config QCOM_SPMI_IADC
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called qcom-spmi-iadc.
|
||||
|
||||
config QCOM_SPMI_VADC
|
||||
tristate "Qualcomm SPMI PMIC voltage ADC"
|
||||
depends on SPMI
|
||||
select REGMAP_SPMI
|
||||
help
|
||||
This is the IIO Voltage ADC driver for Qualcomm QPNP VADC Chip.
|
||||
|
||||
The driver supports multiple channels read. The VADC is a 15-bit
|
||||
sigma-delta ADC. Some of the channels are internally used for
|
||||
calibration.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called qcom-spmi-vadc.
|
||||
|
||||
config ROCKCHIP_SARADC
|
||||
tristate "Rockchip SARADC driver"
|
||||
depends on ARCH_ROCKCHIP || (ARM && COMPILE_TEST)
|
||||
|
||||
@@ -15,6 +15,7 @@ obj-$(CONFIG_AD7887) += ad7887.o
|
||||
obj-$(CONFIG_AD799X) += ad799x.o
|
||||
obj-$(CONFIG_AT91_ADC) += at91_adc.o
|
||||
obj-$(CONFIG_AXP288_ADC) += axp288_adc.o
|
||||
obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o
|
||||
obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
|
||||
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
|
||||
obj-$(CONFIG_MAX1027) += max1027.o
|
||||
@@ -24,6 +25,7 @@ obj-$(CONFIG_MCP3422) += mcp3422.o
|
||||
obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
|
||||
obj-$(CONFIG_NAU7802) += nau7802.o
|
||||
obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
|
||||
obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
|
||||
obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
|
||||
obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
|
||||
obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o
|
||||
|
||||
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2015 Imagination Technologies Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
|
||||
/* Registers */
|
||||
#define CC10001_ADC_CONFIG 0x00
|
||||
#define CC10001_ADC_START_CONV BIT(4)
|
||||
#define CC10001_ADC_MODE_SINGLE_CONV BIT(5)
|
||||
|
||||
#define CC10001_ADC_DDATA_OUT 0x04
|
||||
#define CC10001_ADC_EOC 0x08
|
||||
#define CC10001_ADC_EOC_SET BIT(0)
|
||||
|
||||
#define CC10001_ADC_CHSEL_SAMPLED 0x0c
|
||||
#define CC10001_ADC_POWER_UP 0x10
|
||||
#define CC10001_ADC_POWER_UP_SET BIT(0)
|
||||
#define CC10001_ADC_DEBUG 0x14
|
||||
#define CC10001_ADC_DATA_COUNT 0x20
|
||||
|
||||
#define CC10001_ADC_DATA_MASK GENMASK(9, 0)
|
||||
#define CC10001_ADC_NUM_CHANNELS 8
|
||||
#define CC10001_ADC_CH_MASK GENMASK(2, 0)
|
||||
|
||||
#define CC10001_INVALID_SAMPLED 0xffff
|
||||
#define CC10001_MAX_POLL_COUNT 20
|
||||
|
||||
/*
|
||||
* As per device specification, wait six clock cycles after power-up to
|
||||
* activate START. Since adding two more clock cycles delay does not
|
||||
* impact the performance too much, we are adding two additional cycles delay
|
||||
* intentionally here.
|
||||
*/
|
||||
#define CC10001_WAIT_CYCLES 8
|
||||
|
||||
struct cc10001_adc_device {
|
||||
void __iomem *reg_base;
|
||||
struct clk *adc_clk;
|
||||
struct regulator *reg;
|
||||
u16 *buf;
|
||||
|
||||
struct mutex lock;
|
||||
unsigned long channel_map;
|
||||
unsigned int start_delay_ns;
|
||||
unsigned int eoc_delay_ns;
|
||||
};
|
||||
|
||||
static inline void cc10001_adc_write_reg(struct cc10001_adc_device *adc_dev,
|
||||
u32 reg, u32 val)
|
||||
{
|
||||
writel(val, adc_dev->reg_base + reg);
|
||||
}
|
||||
|
||||
static inline u32 cc10001_adc_read_reg(struct cc10001_adc_device *adc_dev,
|
||||
u32 reg)
|
||||
{
|
||||
return readl(adc_dev->reg_base + reg);
|
||||
}
|
||||
|
||||
static void cc10001_adc_start(struct cc10001_adc_device *adc_dev,
|
||||
unsigned int channel)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* Channel selection and mode of operation */
|
||||
val = (channel & CC10001_ADC_CH_MASK) | CC10001_ADC_MODE_SINGLE_CONV;
|
||||
cc10001_adc_write_reg(adc_dev, CC10001_ADC_CONFIG, val);
|
||||
|
||||
val = cc10001_adc_read_reg(adc_dev, CC10001_ADC_CONFIG);
|
||||
val = val | CC10001_ADC_START_CONV;
|
||||
cc10001_adc_write_reg(adc_dev, CC10001_ADC_CONFIG, val);
|
||||
}
|
||||
|
||||
static u16 cc10001_adc_poll_done(struct iio_dev *indio_dev,
|
||||
unsigned int channel,
|
||||
unsigned int delay)
|
||||
{
|
||||
struct cc10001_adc_device *adc_dev = iio_priv(indio_dev);
|
||||
unsigned int poll_count = 0;
|
||||
|
||||
while (!(cc10001_adc_read_reg(adc_dev, CC10001_ADC_EOC) &
|
||||
CC10001_ADC_EOC_SET)) {
|
||||
|
||||
ndelay(delay);
|
||||
if (poll_count++ == CC10001_MAX_POLL_COUNT)
|
||||
return CC10001_INVALID_SAMPLED;
|
||||
}
|
||||
|
||||
poll_count = 0;
|
||||
while ((cc10001_adc_read_reg(adc_dev, CC10001_ADC_CHSEL_SAMPLED) &
|
||||
CC10001_ADC_CH_MASK) != channel) {
|
||||
|
||||
ndelay(delay);
|
||||
if (poll_count++ == CC10001_MAX_POLL_COUNT)
|
||||
return CC10001_INVALID_SAMPLED;
|
||||
}
|
||||
|
||||
/* Read the 10 bit output register */
|
||||
return cc10001_adc_read_reg(adc_dev, CC10001_ADC_DDATA_OUT) &
|
||||
CC10001_ADC_DATA_MASK;
|
||||
}
|
||||
|
||||
static irqreturn_t cc10001_adc_trigger_h(int irq, void *p)
|
||||
{
|
||||
struct cc10001_adc_device *adc_dev;
|
||||
struct iio_poll_func *pf = p;
|
||||
struct iio_dev *indio_dev;
|
||||
unsigned int delay_ns;
|
||||
unsigned int channel;
|
||||
bool sample_invalid;
|
||||
u16 *data;
|
||||
int i;
|
||||
|
||||
indio_dev = pf->indio_dev;
|
||||
adc_dev = iio_priv(indio_dev);
|
||||
data = adc_dev->buf;
|
||||
|
||||
mutex_lock(&adc_dev->lock);
|
||||
|
||||
cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_UP,
|
||||
CC10001_ADC_POWER_UP_SET);
|
||||
|
||||
/* Wait for 8 (6+2) clock cycles before activating START */
|
||||
ndelay(adc_dev->start_delay_ns);
|
||||
|
||||
/* Calculate delay step for eoc and sampled data */
|
||||
delay_ns = adc_dev->eoc_delay_ns / CC10001_MAX_POLL_COUNT;
|
||||
|
||||
i = 0;
|
||||
sample_invalid = false;
|
||||
for_each_set_bit(channel, indio_dev->active_scan_mask,
|
||||
indio_dev->masklength) {
|
||||
|
||||
cc10001_adc_start(adc_dev, channel);
|
||||
|
||||
data[i] = cc10001_adc_poll_done(indio_dev, channel, delay_ns);
|
||||
if (data[i] == CC10001_INVALID_SAMPLED) {
|
||||
dev_warn(&indio_dev->dev,
|
||||
"invalid sample on channel %d\n", channel);
|
||||
sample_invalid = true;
|
||||
goto done;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
done:
|
||||
cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_UP, 0);
|
||||
|
||||
mutex_unlock(&adc_dev->lock);
|
||||
|
||||
if (!sample_invalid)
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, data,
|
||||
iio_get_time_ns());
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static u16 cc10001_adc_read_raw_voltage(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan)
|
||||
{
|
||||
struct cc10001_adc_device *adc_dev = iio_priv(indio_dev);
|
||||
unsigned int delay_ns;
|
||||
u16 val;
|
||||
|
||||
cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_UP,
|
||||
CC10001_ADC_POWER_UP_SET);
|
||||
|
||||
/* Wait for 8 (6+2) clock cycles before activating START */
|
||||
ndelay(adc_dev->start_delay_ns);
|
||||
|
||||
/* Calculate delay step for eoc and sampled data */
|
||||
delay_ns = adc_dev->eoc_delay_ns / CC10001_MAX_POLL_COUNT;
|
||||
|
||||
cc10001_adc_start(adc_dev, chan->channel);
|
||||
|
||||
val = cc10001_adc_poll_done(indio_dev, chan->channel, delay_ns);
|
||||
|
||||
cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_UP, 0);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int cc10001_adc_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct cc10001_adc_device *adc_dev = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
if (iio_buffer_enabled(indio_dev))
|
||||
return -EBUSY;
|
||||
mutex_lock(&adc_dev->lock);
|
||||
*val = cc10001_adc_read_raw_voltage(indio_dev, chan);
|
||||
mutex_unlock(&adc_dev->lock);
|
||||
|
||||
if (*val == CC10001_INVALID_SAMPLED)
|
||||
return -EIO;
|
||||
return IIO_VAL_INT;
|
||||
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
ret = regulator_get_voltage(adc_dev->reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = ret / 1000;
|
||||
*val2 = chan->scan_type.realbits;
|
||||
return IIO_VAL_FRACTIONAL_LOG2;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int cc10001_update_scan_mode(struct iio_dev *indio_dev,
|
||||
const unsigned long *scan_mask)
|
||||
{
|
||||
struct cc10001_adc_device *adc_dev = iio_priv(indio_dev);
|
||||
|
||||
kfree(adc_dev->buf);
|
||||
adc_dev->buf = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
|
||||
if (!adc_dev->buf)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iio_info cc10001_adc_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = &cc10001_adc_read_raw,
|
||||
.update_scan_mode = &cc10001_update_scan_mode,
|
||||
};
|
||||
|
||||
static int cc10001_adc_channel_init(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct cc10001_adc_device *adc_dev = iio_priv(indio_dev);
|
||||
struct iio_chan_spec *chan_array, *timestamp;
|
||||
unsigned int bit, idx = 0;
|
||||
|
||||
indio_dev->num_channels = bitmap_weight(&adc_dev->channel_map,
|
||||
CC10001_ADC_NUM_CHANNELS);
|
||||
|
||||
chan_array = devm_kcalloc(&indio_dev->dev, indio_dev->num_channels + 1,
|
||||
sizeof(struct iio_chan_spec),
|
||||
GFP_KERNEL);
|
||||
if (!chan_array)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_set_bit(bit, &adc_dev->channel_map, CC10001_ADC_NUM_CHANNELS) {
|
||||
struct iio_chan_spec *chan = &chan_array[idx];
|
||||
|
||||
chan->type = IIO_VOLTAGE;
|
||||
chan->indexed = 1;
|
||||
chan->channel = bit;
|
||||
chan->scan_index = idx;
|
||||
chan->scan_type.sign = 'u';
|
||||
chan->scan_type.realbits = 10;
|
||||
chan->scan_type.storagebits = 16;
|
||||
chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
|
||||
chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
|
||||
idx++;
|
||||
}
|
||||
|
||||
timestamp = &chan_array[idx];
|
||||
timestamp->type = IIO_TIMESTAMP;
|
||||
timestamp->channel = -1;
|
||||
timestamp->scan_index = idx;
|
||||
timestamp->scan_type.sign = 's';
|
||||
timestamp->scan_type.realbits = 64;
|
||||
timestamp->scan_type.storagebits = 64;
|
||||
|
||||
indio_dev->channels = chan_array;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cc10001_adc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct cc10001_adc_device *adc_dev;
|
||||
unsigned long adc_clk_rate;
|
||||
struct resource *res;
|
||||
struct iio_dev *indio_dev;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
adc_dev = iio_priv(indio_dev);
|
||||
|
||||
adc_dev->channel_map = GENMASK(CC10001_ADC_NUM_CHANNELS - 1, 0);
|
||||
if (!of_property_read_u32(node, "adc-reserved-channels", &ret))
|
||||
adc_dev->channel_map &= ~ret;
|
||||
|
||||
adc_dev->reg = devm_regulator_get(&pdev->dev, "vref");
|
||||
if (IS_ERR(adc_dev->reg))
|
||||
return PTR_ERR(adc_dev->reg);
|
||||
|
||||
ret = regulator_enable(adc_dev->reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
indio_dev->dev.parent = &pdev->dev;
|
||||
indio_dev->name = dev_name(&pdev->dev);
|
||||
indio_dev->info = &cc10001_adc_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
adc_dev->reg_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(adc_dev->reg_base)) {
|
||||
ret = PTR_ERR(adc_dev->reg_base);
|
||||
goto err_disable_reg;
|
||||
}
|
||||
|
||||
adc_dev->adc_clk = devm_clk_get(&pdev->dev, "adc");
|
||||
if (IS_ERR(adc_dev->adc_clk)) {
|
||||
dev_err(&pdev->dev, "failed to get the clock\n");
|
||||
ret = PTR_ERR(adc_dev->adc_clk);
|
||||
goto err_disable_reg;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(adc_dev->adc_clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to enable the clock\n");
|
||||
goto err_disable_reg;
|
||||
}
|
||||
|
||||
adc_clk_rate = clk_get_rate(adc_dev->adc_clk);
|
||||
if (!adc_clk_rate) {
|
||||
ret = -EINVAL;
|
||||
dev_err(&pdev->dev, "null clock rate!\n");
|
||||
goto err_disable_clk;
|
||||
}
|
||||
|
||||
adc_dev->eoc_delay_ns = NSEC_PER_SEC / adc_clk_rate;
|
||||
adc_dev->start_delay_ns = adc_dev->eoc_delay_ns * CC10001_WAIT_CYCLES;
|
||||
|
||||
/* Setup the ADC channels available on the device */
|
||||
ret = cc10001_adc_channel_init(indio_dev);
|
||||
if (ret < 0)
|
||||
goto err_disable_clk;
|
||||
|
||||
mutex_init(&adc_dev->lock);
|
||||
|
||||
ret = iio_triggered_buffer_setup(indio_dev, NULL,
|
||||
&cc10001_adc_trigger_h, NULL);
|
||||
if (ret < 0)
|
||||
goto err_disable_clk;
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret < 0)
|
||||
goto err_cleanup_buffer;
|
||||
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_cleanup_buffer:
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
err_disable_clk:
|
||||
clk_disable_unprepare(adc_dev->adc_clk);
|
||||
err_disable_reg:
|
||||
regulator_disable(adc_dev->reg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cc10001_adc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||
struct cc10001_adc_device *adc_dev = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
clk_disable_unprepare(adc_dev->adc_clk);
|
||||
regulator_disable(adc_dev->reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id cc10001_adc_dt_ids[] = {
|
||||
{ .compatible = "cosmic,10001-adc", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cc10001_adc_dt_ids);
|
||||
|
||||
static struct platform_driver cc10001_adc_driver = {
|
||||
.driver = {
|
||||
.name = "cc10001-adc",
|
||||
.of_match_table = cc10001_adc_dt_ids,
|
||||
},
|
||||
.probe = cc10001_adc_probe,
|
||||
.remove = cc10001_adc_remove,
|
||||
};
|
||||
module_platform_driver(cc10001_adc_driver);
|
||||
|
||||
MODULE_AUTHOR("Phani Movva <Phani.Movva@imgtec.com>");
|
||||
MODULE_DESCRIPTION("Cosmic Circuits ADC driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user