提交 46f7b635 编写于 作者: L Linus Torvalds

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

Pull staging drivers patches from Greg KH:
 "Here's the big staging driver tree update for 3.20-rc1.

  Lots of little things in here, adding up to lots of overall cleanups.
  The IIO driver updates are also in here as they cross the staging tree
  boundry a lot.  I2O has moved into staging as well, as a plan to drop
  it from the tree eventually as that's a dead subsystem.

  All of this has been in linux-next with no reported issues for a
  while"

* tag 'staging-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (740 commits)
  staging: lustre: lustre: libcfs: define symbols as static
  staging: rtl8712: Do coding style cleanup
  staging: lustre: make obd_updatemax_lock static
  staging: rtl8188eu: core: switch with redundant cases
  staging: rtl8188eu: odm: conditional setting with no effect
  staging: rtl8188eu: odm: condition with no effect
  staging: ft1000: fix braces warning
  staging: sm7xxfb: fix remaining CamelCase
  staging: sm7xxfb: fix CamelCase
  staging: rtl8723au: multiple condition with no effect - if identical to else
  staging: sm7xxfb: make smtc_scr_info static
  staging/lustre/mdc: Initialize req in mdc_enqueue for !it case
  staging/lustre/clio: Do not allow group locks with gid 0
  staging/lustre/llite: don't add to page cache upon failure
  staging/lustre/llite: Add exception entry check after radix_tree
  staging/lustre/libcfs: protect kkuc_groups from write access
  staging/lustre/fld: refer to MDT0 for fld lookup in some cases
  staging/lustre/llite: Solve a race to access lli_has_smd in read case
  staging/lustre/ptlrpc: hold rq_lock when modify rq_flags
  staging/lustre/lnet: portal spreading rotor should be unsigned
  ...
......@@ -92,6 +92,18 @@ Description:
is required is a consistent labeling. Units after application
of scale and offset are millivolts.
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_raw
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_supply_raw
KernelVersion: 3.17
Contact: linux-iio@vger.kernel.org
Description:
Raw (unscaled no bias removal etc.) current measurement from
channel Y. In special cases where the channel does not
correspond to externally available input one of the named
versions may be used. The number must always be specified and
unique to allow association with event codes. Units after
application of scale and offset are milliamps.
What: /sys/bus/iio/devices/iio:deviceX/in_capacitanceY_raw
KernelVersion: 3.2
Contact: linux-iio@vger.kernel.org
......@@ -234,6 +246,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_offset
What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_offset
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_offset
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_offset
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_offset
What: /sys/bus/iio/devices/iio:deviceX/in_current_offset
What: /sys/bus/iio/devices/iio:deviceX/in_tempY_offset
What: /sys/bus/iio/devices/iio:deviceX/in_temp_offset
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_offset
......@@ -262,9 +276,14 @@ What: /sys/bus/iio/devices/iio:deviceX/in_voltage_scale
What: /sys/bus/iio/devices/iio:deviceX/in_voltage-voltage_scale
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_scale
What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_scale
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_scale
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_supply_scale
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
......@@ -276,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:
......@@ -323,6 +343,44 @@ Description:
production inaccuracies). If shared across all channels,
<type>_calibscale is used.
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 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
......@@ -783,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:
......@@ -790,6 +856,40 @@ Description:
met before an event is generated. If direction is not
specified then this period applies to both directions.
What: /sys/.../events/in_activity_still_thresh_rising_en
What: /sys/.../events/in_activity_still_thresh_falling_en
What: /sys/.../events/in_activity_walking_thresh_rising_en
What: /sys/.../events/in_activity_walking_thresh_falling_en
What: /sys/.../events/in_activity_jogging_thresh_rising_en
What: /sys/.../events/in_activity_jogging_thresh_falling_en
What: /sys/.../events/in_activity_running_thresh_rising_en
What: /sys/.../events/in_activity_running_thresh_falling_en
KernelVersion: 3.19
Contact: linux-iio@vger.kernel.org
Description:
Enables or disables activitity events. Depending on direction
an event is generated when sensor ENTERS or LEAVES a given state.
What: /sys/.../events/in_activity_still_thresh_rising_value
What: /sys/.../events/in_activity_still_thresh_falling_value
What: /sys/.../events/in_activity_walking_thresh_rising_value
What: /sys/.../events/in_activity_walking_thresh_falling_value
What: /sys/.../events/in_activity_jogging_thresh_rising_value
What: /sys/.../events/in_activity_jogging_thresh_falling_value
What: /sys/.../events/in_activity_running_thresh_rising_value
What: /sys/.../events/in_activity_running_thresh_falling_value
KernelVersion: 3.19
Contact: linux-iio@vger.kernel.org
Description:
Confidence value (in units as percentage) to be used
for deciding when an event should be generated. E.g for
running: If the confidence value reported by the sensor
is greater than in_activity_running_thresh_rising_value
then the sensor ENTERS running state. Conversely, if the
confidence value reported by the sensor is lower than
in_activity_running_thresh_falling_value then the sensor
is LEAVING running state.
What: /sys/.../iio:deviceX/events/in_accel_mag_en
What: /sys/.../iio:deviceX/events/in_accel_mag_rising_en
What: /sys/.../iio:deviceX/events/in_accel_mag_falling_en
......@@ -822,6 +922,25 @@ Description:
number or direction is not specified, applies to all channels of
this type.
What: /sys/.../events/in_steps_change_en
KernelVersion: 3.20
Contact: linux-iio@vger.kernel.org
Description:
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
Contact: linux-iio@vger.kernel.org
......@@ -956,6 +1075,16 @@ Description:
and the relevant _type attributes to establish the data storage
format.
What: /sys/.../iio:deviceX/in_activity_still_input
What: /sys/.../iio:deviceX/in_activity_walking_input
What: /sys/.../iio:deviceX/in_activity_jogging_input
What: /sys/.../iio:deviceX/in_activity_running_input
KernelVersion: 3.19
Contact: linux-iio@vger.kernel.org
Description:
This attribute is used to read the confidence for an activity
expressed in units as percentage.
What: /sys/.../iio:deviceX/in_anglvel_z_quadrature_correction_raw
KernelVersion: 2.6.38
Contact: linux-iio@vger.kernel.org
......@@ -973,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
......@@ -992,7 +1139,9 @@ Description:
reflectivity of infrared or ultrasound emitted.
Often these sensors are unit less and as such conversion
to SI units is not possible. Where it is, the units should
be meters.
be meters. If such a conversion is not possible, the reported
values should behave in the same way as a distance, i.e. lower
values indicate something is closer to the sensor.
What: /sys/.../iio:deviceX/in_illuminanceY_input
What: /sys/.../iio:deviceX/in_illuminanceY_raw
......@@ -1024,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
......@@ -1051,3 +1206,46 @@ Description:
after application of scale and offset. If no offset or scale is
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 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
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.
......@@ -35,6 +35,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
......
* 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 = <&reg_1v8>;
};
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";
};
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>;
};
......@@ -12,9 +12,9 @@ Optional properties:
property is not present, then the touchscreen is
disabled. 5 wires is valid for i.MX28 SoC only.
- fsl,ave-ctrl: number of samples per direction to calculate an average value.
Allowed value is 1 ... 31, default is 4
Allowed value is 1 ... 32, default is 4
- fsl,ave-delay: delay between consecutive samples. Allowed value is
1 ... 2047. It is used if 'fsl,ave-ctrl' > 1, counts at
2 ... 2048. It is used if 'fsl,ave-ctrl' > 1, counts at
2 kHz and its default is 2 (= 1 ms)
- fsl,settling: delay between plate switch to next sample. Allowed value is
1 ... 2047. It counts at 2 kHz and its default is
......
......@@ -38,6 +38,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.
......
......@@ -258,6 +258,8 @@ IIO
devm_iio_device_free()
devm_iio_device_register()
devm_iio_device_unregister()
devm_iio_kfifo_allocate()
devm_iio_kfifo_free()
devm_iio_trigger_alloc()
devm_iio_trigger_free()
......
......@@ -2399,6 +2399,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
......@@ -3904,6 +3910,12 @@ S: Supported
F: Documentation/fault-injection/
F: lib/fault-inject.c
FBTFT Framebuffer drivers
M: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
M: Noralf Trønnes <noralf@tronnes.org>
S: Maintained
F: drivers/staging/fbtft/
FCOE SUBSYSTEM (libfc, libfcoe, fcoe)
M: Robert Love <robert.w.love@intel.com>
L: fcoe-devel@open-fcoe.org
......@@ -9262,6 +9274,14 @@ L: linux-wireless@vger.kernel.org
S: Maintained
F: drivers/staging/rtl8723au/
STAGING - SILICON MOTION SM7XX FRAME BUFFER DRIVER
M: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
M: Teddy Wang <teddy.wang@siliconmotion.com>
M: Sudip Mukherjee <sudip@vectorindia.org>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/staging/sm7xxfb/
STAGING - SLICOSS
M: Lior Dotan <liodot@gmail.com>
M: Christopher Harrer <charrer@alacritech.com>
......
......@@ -36,8 +36,6 @@ source "drivers/message/fusion/Kconfig"
source "drivers/firewire/Kconfig"
source "drivers/message/i2o/Kconfig"
source "drivers/macintosh/Kconfig"
source "drivers/net/Kconfig"
......
......@@ -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
......
......@@ -43,6 +43,9 @@ config HID_SENSOR_ACCEL_3D
Say yes here to build support for the HID SENSOR
accelerometers 3D.
To compile this driver as a module, choose M here: the
module will be called hid-sensor-accel-3d.
config IIO_ST_ACCEL_3AXIS
tristate "STMicroelectronics accelerometers 3-Axis Driver"
depends on (I2C || SPI_MASTER) && SYSFS
......@@ -80,6 +83,9 @@ config KXSD9
Say yes here to build support for the Kionix KXSD9 accelerometer.
Currently this only supports the device via an SPI interface.
To compile this driver as a module, choose M here: the module
will be called kxsd9.
config MMA8452
tristate "Freescale MMA8452Q Accelerometer Driver"
depends on I2C
......@@ -105,4 +111,29 @@ 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.
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
......@@ -10,6 +10,12 @@ obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
obj-$(CONFIG_KXSD9) += kxsd9.o
obj-$(CONFIG_MMA8452) += mma8452.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
st_accel-$(CONFIG_IIO_BUFFER) += st_accel_buffer.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,
......
......@@ -108,6 +108,7 @@ struct kxcjk1013_data {
bool motion_trigger_on;
int64_t timestamp;
enum kx_chipset chipset;
bool is_smo8500_device;
};
enum kxcjk1013_axis {
......@@ -377,6 +378,7 @@ static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data)
static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
{
#ifdef CONFIG_PM
int ret;
if (on)
......@@ -388,8 +390,11 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
if (ret < 0) {
dev_err(&data->client->dev,
"Failed: kxcjk1013_set_power_state for %d\n", on);
if (on)
pm_runtime_put_noidle(&data->client->dev);
return ret;
}
#endif
return 0;
}
......@@ -858,6 +863,8 @@ static int kxcjk1013_write_event_config(struct iio_dev *indio_dev,
ret = kxcjk1013_setup_any_motion_interrupt(data, state);
if (ret < 0) {
kxcjk1013_set_power_state(data, false);
data->ev_enable_state = 0;
mutex_unlock(&data->mutex);
return ret;
}
......@@ -1008,6 +1015,7 @@ static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig,
else
ret = kxcjk1013_setup_new_data_interrupt(data, state);
if (ret < 0) {
kxcjk1013_set_power_state(data, false);
mutex_unlock(&data->mutex);
return ret;
}
......@@ -1131,12 +1139,16 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private)
}
static const char *kxcjk1013_match_acpi_device(struct device *dev,
enum kx_chipset *chipset)
enum kx_chipset *chipset,
bool *is_smo8500_device)
{
const struct acpi_device_id *id;
id = acpi_match_device(dev->driver->acpi_match_table, dev);
if (!id)
return NULL;
if (strcmp(id->id, "SMO8500") == 0)
*is_smo8500_device = true;
*chipset = (enum kx_chipset)id->driver_data;
return dev_name(dev);
......@@ -1151,6 +1163,8 @@ static int kxcjk1013_gpio_probe(struct i2c_client *client,
if (!client)
return -EINVAL;
if (data->is_smo8500_device)
return -ENOTSUPP;
dev = &client->dev;
......@@ -1200,7 +1214,8 @@ static int kxcjk1013_probe(struct i2c_client *client,
name = id->name;
} else if (ACPI_HANDLE(&client->dev)) {
name = kxcjk1013_match_acpi_device(&client->dev,
&data->chipset);
&data->chipset,
&data->is_smo8500_device);
} else
return -ENODEV;
......@@ -1228,21 +1243,25 @@ static int kxcjk1013_probe(struct i2c_client *client,
KXCJK1013_IRQ_NAME,
indio_dev);
if (ret)
return ret;
goto err_poweroff;
data->dready_trig = devm_iio_trigger_alloc(&client->dev,
"%s-dev%d",
indio_dev->name,
indio_dev->id);
if (!data->dready_trig)
return -ENOMEM;
if (!data->dready_trig) {
ret = -ENOMEM;
goto err_poweroff;
}
data->motion_trig = devm_iio_trigger_alloc(&client->dev,
"%s-any-motion-dev%d",
indio_dev->name,
indio_dev->id);
if (!data->motion_trig)
return -ENOMEM;
if (!data->motion_trig) {
ret = -ENOMEM;
goto err_poweroff;
}
data->dready_trig->dev.parent = &client->dev;
data->dready_trig->ops = &kxcjk1013_trigger_ops;
......@@ -1251,7 +1270,7 @@ static int kxcjk1013_probe(struct i2c_client *client,
iio_trigger_get(indio_dev->trig);
ret = iio_trigger_register(data->dready_trig);
if (ret)
return ret;
goto err_poweroff;
data->motion_trig->dev.parent = &client->dev;
data->motion_trig->ops = &kxcjk1013_trigger_ops;
......@@ -1300,6 +1319,8 @@ static int kxcjk1013_probe(struct i2c_client *client,
iio_trigger_unregister(data->dready_trig);
if (data->motion_trig)
iio_trigger_unregister(data->motion_trig);
err_poweroff:
kxcjk1013_set_mode(data, STANDBY);
return ret;
}
......@@ -1349,10 +1370,7 @@ static int kxcjk1013_resume(struct device *dev)
int ret = 0;
mutex_lock(&data->mutex);
/* Check, if the suspend occured while active */
if (data->dready_trigger_on || data->motion_trigger_on ||
data->ev_enable_state)
ret = kxcjk1013_set_mode(data, OPERATION);
ret = kxcjk1013_set_mode(data, OPERATION);
mutex_unlock(&data->mutex);
return ret;
......@@ -1364,8 +1382,14 @@ static int kxcjk1013_runtime_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct kxcjk1013_data *data = iio_priv(indio_dev);
int ret;
return kxcjk1013_set_mode(data, STANDBY);
ret = kxcjk1013_set_mode(data, STANDBY);
if (ret < 0) {
dev_err(&data->client->dev, "powering off device failed\n");
return -EAGAIN;
}
return 0;
}
static int kxcjk1013_runtime_resume(struct device *dev)
......@@ -1399,6 +1423,7 @@ static const struct acpi_device_id kx_acpi_match[] = {
{"KXCJ1013", KXCJK1013},
{"KXCJ1008", KXCJ91008},
{"KXTJ1009", KXTJ21009},
{"SMO8500", KXCJ91008},
{ },
};
MODULE_DEVICE_TABLE(acpi, kx_acpi_match);
......@@ -1407,6 +1432,7 @@ static const struct i2c_device_id kxcjk1013_id[] = {
{"kxcjk1013", KXCJK1013},
{"kxcj91008", KXCJ91008},
{"kxtj21009", KXTJ21009},
{"SMO8500", KXCJ91008},
{}
};
......
......@@ -111,7 +111,7 @@ static const int mma8452_samp_freq[8][2] = {
{6, 250000}, {1, 560000}
};
/*
/*
* Hardware has fullscale of -2G, -4G, -8G corresponding to raw value -2048
* The userspace interface uses m/s^2 and we declare micro units
* So scale factor is given by:
......
/*
* Freescale MMA9551L Intelligent Motion-Sensing Platform driver
* 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.
*/
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
#include <linux/pm_runtime.h>
#include "mma9551_core.h"
#define MMA9551_DRV_NAME "mma9551"
#define MMA9551_IRQ_NAME "mma9551_event"
#define MMA9551_GPIO_NAME "mma9551_int"
#define MMA9551_GPIO_COUNT 4
/* Tilt application (inclination in IIO terms). */
#define MMA9551_TILT_XZ_ANG_REG 0x00
#define MMA9551_TILT_YZ_ANG_REG 0x01
#define MMA9551_TILT_XY_ANG_REG 0x02
#define MMA9551_TILT_ANGFLG BIT(7)
#define MMA9551_TILT_QUAD_REG 0x03
#define MMA9551_TILT_XY_QUAD_SHIFT 0
#define MMA9551_TILT_YZ_QUAD_SHIFT 2
#define MMA9551_TILT_XZ_QUAD_SHIFT 4
#define MMA9551_TILT_CFG_REG 0x01
#define MMA9551_TILT_ANG_THRESH_MASK GENMASK(3, 0)
#define MMA9551_DEFAULT_SAMPLE_RATE 122 /* Hz */
/* Tilt events are mapped to the first three GPIO pins. */
enum mma9551_tilt_axis {
mma9551_x = 0,
mma9551_y,
mma9551_z,
};
struct mma9551_data {
struct i2c_client *client;
struct mutex mutex;
int event_enabled[3];
int irqs[MMA9551_GPIO_COUNT];
};
static int mma9551_read_incli_chan(struct i2c_client *client,
const struct iio_chan_spec *chan,
int *val)
{
u8 quad_shift, angle, quadrant;
u16 reg_addr;
int ret;
switch (chan->channel2) {
case IIO_MOD_X:
reg_addr = MMA9551_TILT_YZ_ANG_REG;
quad_shift = MMA9551_TILT_YZ_QUAD_SHIFT;
break;
case IIO_MOD_Y:
reg_addr = MMA9551_TILT_XZ_ANG_REG;
quad_shift = MMA9551_TILT_XZ_QUAD_SHIFT;
break;
case IIO_MOD_Z:
reg_addr = MMA9551_TILT_XY_ANG_REG;
quad_shift = MMA9551_TILT_XY_QUAD_SHIFT;
break;
default:
return -EINVAL;
}
ret = mma9551_set_power_state(client, true);
if (ret < 0)
return ret;
ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT,
reg_addr, &angle);
if (ret < 0)
goto out_poweroff;
ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT,
MMA9551_TILT_QUAD_REG, &quadrant);
if (ret < 0)
goto out_poweroff;
angle &= ~MMA9551_TILT_ANGFLG;
quadrant = (quadrant >> quad_shift) & 0x03;
if (quadrant == 1 || quadrant == 3)
*val = 90 * (quadrant + 1) - angle;
else
*val = angle + 90 * quadrant;
ret = IIO_VAL_INT;
out_poweroff:
mma9551_set_power_state(client, false);
return ret;
}
static int mma9551_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct mma9551_data *data = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
switch (chan->type) {
case IIO_INCLI:
mutex_lock(&data->mutex);
ret = mma9551_read_incli_chan(data->client, chan, val);
mutex_unlock(&data->mutex);
return ret;
default:
return -EINVAL;
}
case IIO_CHAN_INFO_RAW:
switch (chan->type) {
case IIO_ACCEL:
mutex_lock(&data->mutex);
ret = mma9551_read_accel_chan(data->client,
chan, val, val2);
mutex_unlock(&data->mutex);
return ret;
default:
return -EINVAL;
}
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_ACCEL:
return mma9551_read_accel_scale(val, val2);
default:
return -EINVAL;
}
default:
return -EINVAL;
}
}
static int mma9551_read_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir)
{
struct mma9551_data *data = iio_priv(indio_dev);
switch (chan->type) {
case IIO_INCLI:
/* IIO counts axes from 1, because IIO_NO_MOD is 0. */
return data->event_enabled[chan->channel2 - 1];
default:
return -EINVAL;
}
}
static int mma9551_config_incli_event(struct iio_dev *indio_dev,
enum iio_modifier axis,
int state)
{
struct mma9551_data *data = iio_priv(indio_dev);
enum mma9551_tilt_axis mma_axis;
int ret;
/* IIO counts axes from 1, because IIO_NO_MOD is 0. */
mma_axis = axis - 1;
if (data->event_enabled[mma_axis] == state)
return 0;
if (state == 0) {
ret = mma9551_gpio_config(data->client,
(enum mma9551_gpio_pin)mma_axis,
MMA9551_APPID_NONE, 0, 0);
if (ret < 0)
return ret;
ret = mma9551_set_power_state(data->client, false);
if (ret < 0)
return ret;
} else {
int bitnum;
/* Bit 7 of each angle register holds the angle flag. */
switch (axis) {
case IIO_MOD_X:
bitnum = 7 + 8 * MMA9551_TILT_YZ_ANG_REG;
break;
case IIO_MOD_Y:
bitnum = 7 + 8 * MMA9551_TILT_XZ_ANG_REG;
break;
case IIO_MOD_Z:
bitnum = 7 + 8 * MMA9551_TILT_XY_ANG_REG;
break;
default:
return -EINVAL;
}
ret = mma9551_set_power_state(data->client, true);
if (ret < 0)
return ret;
ret = mma9551_gpio_config(data->client,
(enum mma9551_gpio_pin)mma_axis,
MMA9551_APPID_TILT, bitnum, 0);
if (ret < 0) {
mma9551_set_power_state(data->client, false);
return ret;
}
}
data->event_enabled[mma_axis] = state;
return ret;
}
static int mma9551_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
int state)
{
struct mma9551_data *data = iio_priv(indio_dev);
int ret;
switch (chan->type) {
case IIO_INCLI:
mutex_lock(&data->mutex);
ret = mma9551_config_incli_event(indio_dev,
chan->channel2, state);
mutex_unlock(&data->mutex);
return ret;
default:
return -EINVAL;
}
}
static int mma9551_write_event_value(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
enum iio_event_info info,
int val, int val2)
{
struct mma9551_data *data = iio_priv(indio_dev);
int ret;
switch (chan->type) {
case IIO_INCLI:
if (val2 != 0 || val < 1 || val > 10)
return -EINVAL;
mutex_lock(&data->mutex);
ret = mma9551_update_config_bits(data->client,
MMA9551_APPID_TILT,
MMA9551_TILT_CFG_REG,
MMA9551_TILT_ANG_THRESH_MASK,
val);
mutex_unlock(&data->mutex);
return ret;
default:
return -EINVAL;
}
}
static int mma9551_read_event_value(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
enum iio_event_info info,
int *val, int *val2)
{
struct mma9551_data *data = iio_priv(indio_dev);
int ret;
u8 tmp;
switch (chan->type) {
case IIO_INCLI:
mutex_lock(&data->mutex);
ret = mma9551_read_config_byte(data->client,
MMA9551_APPID_TILT,
MMA9551_TILT_CFG_REG, &tmp);
mutex_unlock(&data->mutex);
if (ret < 0)
return ret;
*val = tmp & MMA9551_TILT_ANG_THRESH_MASK;
*val2 = 0;
return IIO_VAL_INT;
default:
return -EINVAL;
}
}
static const struct iio_event_spec mma9551_incli_event = {
.type = IIO_EV_TYPE_ROC,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_ENABLE),
.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE),
};
#define MMA9551_INCLI_CHANNEL(axis) { \
.type = IIO_INCLI, \
.modified = 1, \
.channel2 = axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
.event_spec = &mma9551_incli_event, \
.num_event_specs = 1, \
}
static const struct iio_chan_spec mma9551_channels[] = {
MMA9551_ACCEL_CHANNEL(IIO_MOD_X),
MMA9551_ACCEL_CHANNEL(IIO_MOD_Y),
MMA9551_ACCEL_CHANNEL(IIO_MOD_Z),
MMA9551_INCLI_CHANNEL(IIO_MOD_X),
MMA9551_INCLI_CHANNEL(IIO_MOD_Y),
MMA9551_INCLI_CHANNEL(IIO_MOD_Z),
};
static const struct iio_info mma9551_info = {
.driver_module = THIS_MODULE,
.read_raw = mma9551_read_raw,
.read_event_config = mma9551_read_event_config,
.write_event_config = mma9551_write_event_config,
.read_event_value = mma9551_read_event_value,
.write_event_value = mma9551_write_event_value,
};
static irqreturn_t mma9551_event_handler(int irq, void *private)
{
struct iio_dev *indio_dev = private;
struct mma9551_data *data = iio_priv(indio_dev);
int i, ret, mma_axis = -1;
u16 reg;
u8 val;
mutex_lock(&data->mutex);
for (i = 0; i < 3; i++)
if (irq == data->irqs[i]) {
mma_axis = i;
break;
}
if (mma_axis == -1) {
/* IRQ was triggered on 4th line, which we don't use. */
dev_warn(&data->client->dev,
"irq triggered on unused line %d\n", data->irqs[3]);
goto out;
}
switch (mma_axis) {
case mma9551_x:
reg = MMA9551_TILT_YZ_ANG_REG;
break;
case mma9551_y:
reg = MMA9551_TILT_XZ_ANG_REG;
break;
case mma9551_z:
reg = MMA9551_TILT_XY_ANG_REG;
break;
}
/*
* Read the angle even though we don't use it, otherwise we
* won't get any further interrupts.
*/
ret = mma9551_read_status_byte(data->client, MMA9551_APPID_TILT,
reg, &val);
if (ret < 0) {
dev_err(&data->client->dev,
"error %d reading tilt register in IRQ\n", ret);
goto out;
}
iio_push_event(indio_dev,
IIO_MOD_EVENT_CODE(IIO_INCLI, 0, (mma_axis + 1),
IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING),
iio_get_time_ns());
out:
mutex_unlock(&data->mutex);
return IRQ_HANDLED;
}
static int mma9551_init(struct mma9551_data *data)
{
int ret;
ret = mma9551_read_version(data->client);
if (ret)
return ret;
return mma9551_set_device_state(data->client, true);
}
static int mma9551_gpio_probe(struct iio_dev *indio_dev)
{
struct gpio_desc *gpio;
int i, ret;
struct mma9551_data *data = iio_priv(indio_dev);
struct device *dev = &data->client->dev;
for (i = 0; i < MMA9551_GPIO_COUNT; i++) {
gpio = devm_gpiod_get_index(dev, MMA9551_GPIO_NAME, i);
if (IS_ERR(gpio)) {
dev_err(dev, "acpi gpio get index failed\n");
return PTR_ERR(gpio);
}
ret = gpiod_direction_input(gpio);
if (ret)
return ret;
data->irqs[i] = gpiod_to_irq(gpio);
ret = devm_request_threaded_irq(dev, data->irqs[i],
NULL, mma9551_event_handler,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
MMA9551_IRQ_NAME, indio_dev);
if (ret < 0) {
dev_err(dev, "request irq %d failed\n", data->irqs[i]);
return ret;
}
dev_dbg(dev, "gpio resource, no:%d irq:%d\n",
desc_to_gpio(gpio), data->irqs[i]);
}
return 0;
}
static const char *mma9551_match_acpi_device(struct device *dev)
{
const struct acpi_device_id *id;
id = acpi_match_device(dev->driver->acpi_match_table, dev);
if (!id)
return NULL;
return dev_name(dev);
}
static int mma9551_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct mma9551_data *data;
struct iio_dev *indio_dev;
const char *name = NULL;
int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
if (id)
name = id->name;
else if (ACPI_HANDLE(&client->dev))
name = mma9551_match_acpi_device(&client->dev);
ret = mma9551_init(data);
if (ret < 0)
return ret;
mutex_init(&data->mutex);
indio_dev->dev.parent = &client->dev;
indio_dev->channels = mma9551_channels;
indio_dev->num_channels = ARRAY_SIZE(mma9551_channels);
indio_dev->name = name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &mma9551_info;
ret = mma9551_gpio_probe(indio_dev);
if (ret < 0)
goto out_poweroff;
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "unable to register iio device\n");
goto out_poweroff;
}
ret = pm_runtime_set_active(&client->dev);
if (ret < 0)
goto out_iio_unregister;
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev,
MMA9551_AUTO_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(&client->dev);
return 0;
out_iio_unregister:
iio_device_unregister(indio_dev);
out_poweroff:
mma9551_set_device_state(client, false);
return ret;
}
static int mma9551_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct mma9551_data *data = iio_priv(indio_dev);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
pm_runtime_put_noidle(&client->dev);
iio_device_unregister(indio_dev);
mutex_lock(&data->mutex);
mma9551_set_device_state(data->client, false);
mutex_unlock(&data->mutex);
return 0;
}
#ifdef CONFIG_PM
static int mma9551_runtime_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct mma9551_data *data = iio_priv(indio_dev);
int ret;
mutex_lock(&data->mutex);
ret = mma9551_set_device_state(data->client, false);
mutex_unlock(&data->mutex);
if (ret < 0) {
dev_err(&data->client->dev, "powering off device failed\n");
return -EAGAIN;
}
return 0;
}
static int mma9551_runtime_resume(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct mma9551_data *data = iio_priv(indio_dev);
int ret;
ret = mma9551_set_device_state(data->client, true);
if (ret < 0)
return ret;
mma9551_sleep(MMA9551_DEFAULT_SAMPLE_RATE);
return 0;
}
#endif
#ifdef CONFIG_PM_SLEEP
static int mma9551_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct mma9551_data *data = iio_priv(indio_dev);
int ret;
mutex_lock(&data->mutex);
ret = mma9551_set_device_state(data->client, false);
mutex_unlock(&data->mutex);
return ret;
}
static int mma9551_resume(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct mma9551_data *data = iio_priv(indio_dev);
int ret;
mutex_lock(&data->mutex);
ret = mma9551_set_device_state(data->client, true);
mutex_unlock(&data->mutex);
return ret;
}
#endif
static const struct dev_pm_ops mma9551_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(mma9551_suspend, mma9551_resume)
SET_RUNTIME_PM_OPS(mma9551_runtime_suspend,
mma9551_runtime_resume, NULL)
};
static const struct acpi_device_id mma9551_acpi_match[] = {
{"MMA9551", 0},
{},
};
MODULE_DEVICE_TABLE(acpi, mma9551_acpi_match);
static const struct i2c_device_id mma9551_id[] = {
{"mma9551", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, mma9551_id);
static struct i2c_driver mma9551_driver = {
.driver = {
.name = MMA9551_DRV_NAME,
.acpi_match_table = ACPI_PTR(mma9551_acpi_match),
.pm = &mma9551_pm_ops,
},
.probe = mma9551_probe,
.remove = mma9551_remove,
.id_table = mma9551_id,
};
module_i2c_driver(mma9551_driver);
MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>");
MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("MMA9551L motion-sensing platform driver");
此差异已折叠。
/*
* 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_ */
此差异已折叠。
/*
* 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
......
/*
* 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");
此差异已折叠。
......@@ -249,7 +249,7 @@ static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev,
struct iio_buffer *buffer;
int ret;
buffer = iio_kfifo_allocate(indio_dev);
buffer = iio_kfifo_allocate();
if (!buffer)
return -ENOMEM;
......@@ -263,16 +263,8 @@ static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev,
indio_dev->setup_ops = setup_ops;
indio_dev->modes |= INDIO_BUFFER_HARDWARE;
ret = iio_buffer_register(indio_dev,
indio_dev->channels,
indio_dev->num_channels);
if (ret)
goto error_free_irq;
return 0;
error_free_irq:
free_irq(irq, indio_dev);
error_kfifo_free:
iio_kfifo_free(indio_dev->buffer);
return ret;
......@@ -284,7 +276,6 @@ static void tiadc_iio_buffered_hardware_remove(struct iio_dev *indio_dev)
free_irq(adc_dev->mfd_tscadc->irq, indio_dev);
iio_kfifo_free(indio_dev->buffer);
iio_buffer_unregister(indio_dev);
}
......
......@@ -31,7 +31,7 @@ struct ad8366_state {
};
static int ad8366_write(struct iio_dev *indio_dev,
unsigned char ch_a, char unsigned ch_b)
unsigned char ch_a, unsigned char ch_b)
{
struct ad8366_state *st = iio_priv(indio_dev);
int ret;
......@@ -166,7 +166,7 @@ static int ad8366_probe(struct spi_device *spi)
if (ret)
goto error_disable_reg;
ad8366_write(indio_dev, 0 , 0);
ad8366_write(indio_dev, 0, 0);
return 0;
......
......@@ -3,4 +3,5 @@
#
source "drivers/iio/common/hid-sensors/Kconfig"
source "drivers/iio/common/ssp_sensors/Kconfig"
source "drivers/iio/common/st_sensors/Kconfig"
......@@ -8,4 +8,5 @@
# When adding new entries keep the list in alphabetical order
obj-y += hid-sensors/
obj-y += ssp_sensors/
obj-y += st_sensors/
......@@ -22,16 +22,18 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/hid-sensor-hub.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
#include <linux/iio/sysfs.h>
#include "hid-sensor-trigger.h"
int hid_sensor_power_state(struct hid_sensor_common *st, bool state)
static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state)
{
int state_val;
int report_val;
s32 poll_value = 0;
if (state) {
if (sensor_hub_device_open(st->hsdev))
......@@ -47,6 +49,8 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state)
st->report_state.report_id,
st->report_state.index,
HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM);
poll_value = hid_sensor_read_poll_value(st);
} else {
if (!atomic_dec_and_test(&st->data_ready))
return 0;
......@@ -78,10 +82,36 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state)
sensor_hub_get_feature(st->hsdev, st->power_state.report_id,
st->power_state.index,
&state_val);
if (state && poll_value)
msleep_interruptible(poll_value * 2);
return 0;
}
EXPORT_SYMBOL(hid_sensor_power_state);
int hid_sensor_power_state(struct hid_sensor_common *st, bool state)
{
#ifdef CONFIG_PM
int ret;
if (state)
ret = pm_runtime_get_sync(&st->pdev->dev);
else {
pm_runtime_mark_last_busy(&st->pdev->dev);
ret = pm_runtime_put_autosuspend(&st->pdev->dev);
}
if (ret < 0) {
if (state)
pm_runtime_put_noidle(&st->pdev->dev);
return ret;
}
return 0;
#else
return _hid_sensor_power_state(st, state);
#endif
}
static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
......@@ -125,8 +155,21 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
attrb->trigger = trig;
indio_dev->trig = iio_trigger_get(trig);
return ret;
ret = pm_runtime_set_active(&indio_dev->dev);
if (ret)
goto error_unreg_trigger;
iio_device_set_drvdata(indio_dev, attrb);
pm_suspend_ignore_children(&attrb->pdev->dev, true);
pm_runtime_enable(&attrb->pdev->dev);
/* Default to 3 seconds, but can be changed from sysfs */
pm_runtime_set_autosuspend_delay(&attrb->pdev->dev,
3000);
pm_runtime_use_autosuspend(&attrb->pdev->dev);
return ret;
error_unreg_trigger:
iio_trigger_unregister(trig);
error_free_trig:
iio_trigger_free(trig);
error_ret:
......@@ -134,6 +177,34 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
}
EXPORT_SYMBOL(hid_sensor_setup_trigger);
#ifdef CONFIG_PM
static int hid_sensor_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
return _hid_sensor_power_state(attrb, false);
}
static int hid_sensor_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
return _hid_sensor_power_state(attrb, true);
}
#endif
const struct dev_pm_ops hid_sensor_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(hid_sensor_suspend, hid_sensor_resume)
SET_RUNTIME_PM_OPS(hid_sensor_suspend,
hid_sensor_resume, NULL)
};
EXPORT_SYMBOL(hid_sensor_pm_ops);
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
MODULE_DESCRIPTION("HID Sensor trigger processing");
MODULE_LICENSE("GPL");
......@@ -19,6 +19,11 @@
#ifndef _HID_SENSOR_TRIGGER_H
#define _HID_SENSOR_TRIGGER_H
#include <linux/pm.h>
#include <linux/pm_runtime.h>
extern const struct dev_pm_ops hid_sensor_pm_ops;
int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
struct hid_sensor_common *attrb);
void hid_sensor_remove_trigger(struct hid_sensor_common *attrb);
......
#
# SSP sensor drivers and commons configuration
#
menu "SSP Sensor Common"
config IIO_SSP_SENSORS_COMMONS
tristate "Commons for all SSP Sensor IIO drivers"
depends on IIO_SSP_SENSORHUB
select IIO_BUFFER
select IIO_KFIFO_BUF
help
Say yes here to build commons for SSP sensors.
To compile this as a module, choose M here: the module
will be called ssp_iio.
config IIO_SSP_SENSORHUB
tristate "Samsung Sensorhub driver"
depends on SPI
select MFD_CORE
help
SSP driver for sensorhub.
If you say yes here you get ssp support for sensorhub.
To compile this driver as a module, choose M here: the
module will be called sensorhub.
endmenu
#
# Makefile for SSP sensor drivers and commons.
#
sensorhub-objs := ssp_dev.o ssp_spi.o
obj-$(CONFIG_IIO_SSP_SENSORHUB) += sensorhub.o
obj-$(CONFIG_IIO_SSP_SENSORS_COMMONS) += ssp_iio.o
/*
* 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.
*
*/
#ifndef __SSP_SENSORHUB_H__
#define __SSP_SENSORHUB_H__
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/iio/common/ssp_sensors.h>
#include <linux/iio/iio.h>
#include <linux/spi/spi.h>
#define SSP_DEVICE_ID 0x55
#ifdef SSP_DBG
#define ssp_dbg(format, ...) pr_info("[SSP] "format, ##__VA_ARGS__)
#else
#define ssp_dbg(format, ...)
#endif
#define SSP_SW_RESET_TIME 3000
/* Sensor polling in ms */
#define SSP_DEFAULT_POLLING_DELAY 200
#define SSP_DEFAULT_RETRIES 3
#define SSP_DATA_PACKET_SIZE 960
#define SSP_HEADER_BUFFER_SIZE 4
enum {
SSP_KERNEL_BINARY = 0,
SSP_KERNEL_CRASHED_BINARY,
};
enum {
SSP_INITIALIZATION_STATE = 0,
SSP_NO_SENSOR_STATE,
SSP_ADD_SENSOR_STATE,
SSP_RUNNING_SENSOR_STATE,
};
/* Firmware download STATE */
enum {
SSP_FW_DL_STATE_FAIL = -1,
SSP_FW_DL_STATE_NONE = 0,
SSP_FW_DL_STATE_NEED_TO_SCHEDULE,
SSP_FW_DL_STATE_SCHEDULED,
SSP_FW_DL_STATE_DOWNLOADING,
SSP_FW_DL_STATE_SYNC,
SSP_FW_DL_STATE_DONE,
};
#define SSP_INVALID_REVISION 99999
#define SSP_INVALID_REVISION2 0xffffff
/* AP -> SSP Instruction */
#define SSP_MSG2SSP_INST_BYPASS_SENSOR_ADD 0xa1
#define SSP_MSG2SSP_INST_BYPASS_SENSOR_RM 0xa2
#define SSP_MSG2SSP_INST_REMOVE_ALL 0xa3
#define SSP_MSG2SSP_INST_CHANGE_DELAY 0xa4
#define SSP_MSG2SSP_INST_LIBRARY_ADD 0xb1
#define SSP_MSG2SSP_INST_LIBRARY_REMOVE 0xb2
#define SSP_MSG2SSP_INST_LIB_NOTI 0xb4
#define SSP_MSG2SSP_INST_LIB_DATA 0xc1
#define SSP_MSG2SSP_AP_MCU_SET_GYRO_CAL 0xcd
#define SSP_MSG2SSP_AP_MCU_SET_ACCEL_CAL 0xce
#define SSP_MSG2SSP_AP_STATUS_SHUTDOWN 0xd0
#define SSP_MSG2SSP_AP_STATUS_WAKEUP 0xd1
#define SSP_MSG2SSP_AP_STATUS_SLEEP 0xd2
#define SSP_MSG2SSP_AP_STATUS_RESUME 0xd3
#define SSP_MSG2SSP_AP_STATUS_SUSPEND 0xd4
#define SSP_MSG2SSP_AP_STATUS_RESET 0xd5
#define SSP_MSG2SSP_AP_STATUS_POW_CONNECTED 0xd6
#define SSP_MSG2SSP_AP_STATUS_POW_DISCONNECTED 0xd7
#define SSP_MSG2SSP_AP_TEMPHUMIDITY_CAL_DONE 0xda
#define SSP_MSG2SSP_AP_MCU_SET_DUMPMODE 0xdb
#define SSP_MSG2SSP_AP_MCU_DUMP_CHECK 0xdc
#define SSP_MSG2SSP_AP_MCU_BATCH_FLUSH 0xdd
#define SSP_MSG2SSP_AP_MCU_BATCH_COUNT 0xdf
#define SSP_MSG2SSP_AP_WHOAMI 0x0f
#define SSP_MSG2SSP_AP_FIRMWARE_REV 0xf0
#define SSP_MSG2SSP_AP_SENSOR_FORMATION 0xf1
#define SSP_MSG2SSP_AP_SENSOR_PROXTHRESHOLD 0xf2
#define SSP_MSG2SSP_AP_SENSOR_BARCODE_EMUL 0xf3
#define SSP_MSG2SSP_AP_SENSOR_SCANNING 0xf4
#define SSP_MSG2SSP_AP_SET_MAGNETIC_HWOFFSET 0xf5
#define SSP_MSG2SSP_AP_GET_MAGNETIC_HWOFFSET 0xf6
#define SSP_MSG2SSP_AP_SENSOR_GESTURE_CURRENT 0xf7
#define SSP_MSG2SSP_AP_GET_THERM 0xf8
#define SSP_MSG2SSP_AP_GET_BIG_DATA 0xf9
#define SSP_MSG2SSP_AP_SET_BIG_DATA 0xfa
#define SSP_MSG2SSP_AP_START_BIG_DATA 0xfb
#define SSP_MSG2SSP_AP_SET_MAGNETIC_STATIC_MATRIX 0xfd
#define SSP_MSG2SSP_AP_SENSOR_TILT 0xea
#define SSP_MSG2SSP_AP_MCU_SET_TIME 0xfe
#define SSP_MSG2SSP_AP_MCU_GET_TIME 0xff
#define SSP_MSG2SSP_AP_FUSEROM 0x01
/* voice data */
#define SSP_TYPE_WAKE_UP_VOICE_SERVICE 0x01
#define SSP_TYPE_WAKE_UP_VOICE_SOUND_SOURCE_AM 0x01
#define SSP_TYPE_WAKE_UP_VOICE_SOUND_SOURCE_GRAMMER 0x02
/* Factory Test */
#define SSP_ACCELEROMETER_FACTORY 0x80
#define SSP_GYROSCOPE_FACTORY 0x81
#define SSP_GEOMAGNETIC_FACTORY 0x82
#define SSP_PRESSURE_FACTORY 0x85
#define SSP_GESTURE_FACTORY 0x86
#define SSP_TEMPHUMIDITY_CRC_FACTORY 0x88
#define SSP_GYROSCOPE_TEMP_FACTORY 0x8a
#define SSP_GYROSCOPE_DPS_FACTORY 0x8b
#define SSP_MCU_FACTORY 0x8c
#define SSP_MCU_SLEEP_FACTORY 0x8d
/* SSP -> AP ACK about write CMD */
#define SSP_MSG_ACK 0x80 /* ACK from SSP to AP */
#define SSP_MSG_NAK 0x70 /* NAK from SSP to AP */
struct ssp_sensorhub_info {
char *fw_name;
char *fw_crashed_name;
unsigned int fw_rev;
const u8 * const mag_table;
const unsigned int mag_length;
};
/* ssp_msg options bit */
#define SSP_RW 0
#define SSP_INDEX 3
#define SSP_AP2HUB_READ 0
#define SSP_AP2HUB_WRITE 1
#define SSP_HUB2AP_WRITE 2
#define SSP_AP2HUB_READY 3
#define SSP_AP2HUB_RETURN 4
/**
* struct ssp_data - ssp platformdata structure
* @spi: spi device
* @sensorhub_info: info about sensorhub board specific features
* @wdt_timer: watchdog timer
* @work_wdt: watchdog work
* @work_firmware: firmware upgrade work queue
* @work_refresh: refresh work queue for reset request from MCU
* @shut_down: shut down flag
* @mcu_dump_mode: mcu dump mode for debug
* @time_syncing: time syncing indication flag
* @timestamp: previous time in ns calculated for time syncing
* @check_status: status table for each sensor
* @com_fail_cnt: communication fail count
* @reset_cnt: reset count
* @timeout_cnt: timeout count
* @available_sensors: available sensors seen by sensorhub (bit array)
* @cur_firm_rev: cached current firmware revision
* @last_resume_state: last AP resume/suspend state used to handle the PM
* state of ssp
* @last_ap_state: (obsolete) sleep notification for MCU
* @sensor_enable: sensor enable mask
* @delay_buf: data acquisition intervals table
* @batch_latency_buf: yet unknown but existing in communication protocol
* @batch_opt_buf: yet unknown but existing in communication protocol
* @accel_position: yet unknown but existing in communication protocol
* @mag_position: yet unknown but existing in communication protocol
* @fw_dl_state: firmware download state
* @comm_lock: lock protecting the handshake
* @pending_lock: lock protecting pending list and completion
* @mcu_reset_gpio: mcu reset line
* @ap_mcu_gpio: ap to mcu gpio line
* @mcu_ap_gpio: mcu to ap gpio line
* @pending_list: pending list for messages queued to be sent/read
* @sensor_devs: registered IIO devices table
* @enable_refcount: enable reference count for wdt (watchdog timer)
* @header_buffer: cache aligned buffer for packet header
*/
struct ssp_data {
struct spi_device *spi;
struct ssp_sensorhub_info *sensorhub_info;
struct timer_list wdt_timer;
struct work_struct work_wdt;
struct delayed_work work_refresh;
bool shut_down;
bool mcu_dump_mode;
bool time_syncing;
int64_t timestamp;
int check_status[SSP_SENSOR_MAX];
unsigned int com_fail_cnt;
unsigned int reset_cnt;
unsigned int timeout_cnt;
unsigned int available_sensors;
unsigned int cur_firm_rev;
char last_resume_state;
char last_ap_state;
unsigned int sensor_enable;
u32 delay_buf[SSP_SENSOR_MAX];
s32 batch_latency_buf[SSP_SENSOR_MAX];
s8 batch_opt_buf[SSP_SENSOR_MAX];
int accel_position;
int mag_position;
int fw_dl_state;
struct mutex comm_lock;
struct mutex pending_lock;
int mcu_reset_gpio;
int ap_mcu_gpio;
int mcu_ap_gpio;
struct list_head pending_list;
struct iio_dev *sensor_devs[SSP_SENSOR_MAX];
atomic_t enable_refcount;
__le16 header_buffer[SSP_HEADER_BUFFER_SIZE / sizeof(__le16)]
____cacheline_aligned;
};
void ssp_clean_pending_list(struct ssp_data *data);
int ssp_command(struct ssp_data *data, char command, int arg);
int ssp_send_instruction(struct ssp_data *data, u8 inst, u8 sensor_type,
u8 *send_buf, u8 length);
int ssp_irq_msg(struct ssp_data *data);
int ssp_get_chipid(struct ssp_data *data);
int ssp_set_magnetic_matrix(struct ssp_data *data);
unsigned int ssp_get_sensor_scanning_info(struct ssp_data *data);
unsigned int ssp_get_firmware_rev(struct ssp_data *data);
int ssp_queue_ssp_refresh_task(struct ssp_data *data, unsigned int delay);
#endif /* __SSP_SENSORHUB_H__ */
此差异已折叠。
/*
* 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/kfifo_buf.h>
#include <linux/module.h>
#include <linux/slab.h>
#include "ssp_iio_sensor.h"
/**
* ssp_common_buffer_postenable() - generic postenable callback for ssp buffer
*
* @indio_dev: iio device
*
* Returns 0 or negative value in case of error
*/
int ssp_common_buffer_postenable(struct iio_dev *indio_dev)
{
struct ssp_sensor_data *spd = iio_priv(indio_dev);
struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent);
/* the allocation is made in post because scan size is known in this
* moment
* */
spd->buffer = kmalloc(indio_dev->scan_bytes, GFP_KERNEL | GFP_DMA);
if (!spd->buffer)
return -ENOMEM;
return ssp_enable_sensor(data, spd->type,
ssp_get_sensor_delay(data, spd->type));
}
EXPORT_SYMBOL(ssp_common_buffer_postenable);
/**
* ssp_common_buffer_postdisable() - generic postdisable callback for ssp buffer
*
* @indio_dev: iio device
*
* Returns 0 or negative value in case of error
*/
int ssp_common_buffer_postdisable(struct iio_dev *indio_dev)
{
int ret;
struct ssp_sensor_data *spd = iio_priv(indio_dev);
struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent);
ret = ssp_disable_sensor(data, spd->type);
if (ret < 0)
return ret;
kfree(spd->buffer);
return ret;
}
EXPORT_SYMBOL(ssp_common_buffer_postdisable);
/**
* ssp_common_process_data() - Common process data callback for ssp sensors
*
* @indio_dev: iio device
* @buf: source buffer
* @len: sensor data length
* @timestamp: system timestamp
*
* Returns 0 or negative value in case of error
*/
int ssp_common_process_data(struct iio_dev *indio_dev, void *buf,
unsigned int len, int64_t timestamp)
{
__le32 time;
int64_t calculated_time;
struct ssp_sensor_data *spd = iio_priv(indio_dev);
if (indio_dev->scan_bytes == 0)
return 0;
/*
* it always sends full set of samples, remember about available masks
*/
memcpy(spd->buffer, buf, len);
if (indio_dev->scan_timestamp) {
memcpy(&time, &((char *)buf)[len], SSP_TIME_SIZE);
calculated_time =
timestamp + (int64_t)le32_to_cpu(time) * 1000000;
}
return iio_push_to_buffers_with_timestamp(indio_dev, spd->buffer,
calculated_time);
}
EXPORT_SYMBOL(ssp_common_process_data);
MODULE_AUTHOR("Karol Wrona <k.wrona@samsung.com>");
MODULE_DESCRIPTION("Samsung sensorhub commons");
MODULE_LICENSE("GPL");
#ifndef __SSP_IIO_SENSOR_H__
#define __SSP_IIO_SENSOR_H__
#define SSP_CHANNEL_AG(_type, _mod, _index) \
{ \
.type = _type,\
.modified = 1,\
.channel2 = _mod,\
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
.scan_index = _index,\
.scan_type = {\
.sign = 's',\
.realbits = 16,\
.storagebits = 16,\
.shift = 0,\
.endianness = IIO_LE,\
},\
}
/* It is defined here as it is a mixed timestamp */
#define SSP_CHAN_TIMESTAMP(_si) { \
.type = IIO_TIMESTAMP, \
.channel = -1, \
.scan_index = _si, \
.scan_type = { \
.sign = 's', \
.realbits = 64, \
.storagebits = 64, \
}, \
}
#define SSP_MS_PER_S 1000
#define SSP_INVERTED_SCALING_FACTOR 1000000U
#define SSP_FACTOR_WITH_MS \
(SSP_INVERTED_SCALING_FACTOR * SSP_MS_PER_S)
int ssp_common_buffer_postenable(struct iio_dev *indio_dev);
int ssp_common_buffer_postdisable(struct iio_dev *indio_dev);
int ssp_common_process_data(struct iio_dev *indio_dev, void *buf,
unsigned int len, int64_t timestamp);
/* Converts time in ms to frequency */
static inline void ssp_convert_to_freq(u32 time, int *integer_part,
int *fractional)
{
if (time == 0) {
*fractional = 0;
*integer_part = 0;
return;
}
*integer_part = SSP_FACTOR_WITH_MS / time;
*fractional = *integer_part % SSP_INVERTED_SCALING_FACTOR;
*integer_part = *integer_part / SSP_INVERTED_SCALING_FACTOR;
}
/* Converts frequency to time in ms */
static inline int ssp_convert_to_time(int integer_part, int fractional)
{
u64 value;
value = (u64)integer_part * SSP_INVERTED_SCALING_FACTOR + fractional;
if (value == 0)
return 0;
return div64_u64((u64)SSP_FACTOR_WITH_MS, value);
}
#endif /* __SSP_IIO_SENSOR_H__ */
此差异已折叠。
......@@ -54,7 +54,7 @@ static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb,
if (err)
goto acc_spi_read_error;
memcpy(data, tb->rx_buf, len*sizeof(u8));
memcpy(data, tb->rx_buf, len);
mutex_unlock(&tb->buf_lock);
return len;
......
......@@ -445,7 +445,7 @@ static int ad9523_store_eeprom(struct iio_dev *indio_dev)
tmp = 4;
do {
msleep(16);
msleep(20);
ret = ad9523_read(indio_dev,
AD9523_EEPROM_DATA_XFER_STATUS);
if (ret < 0)
......
......@@ -387,10 +387,8 @@ static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev)
int ret;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(dev, "could not allocate memory for platform data\n");
if (!pdata)
return NULL;
}
strncpy(&pdata->name[0], np->name, SPI_NAME_SIZE - 1);
......@@ -613,9 +611,8 @@ static int adf4350_remove(struct spi_device *spi)
if (st->clk)
clk_disable_unprepare(st->clk);
if (!IS_ERR(reg)) {
if (!IS_ERR(reg))
regulator_disable(reg);
}
return 0;
}
......
......@@ -16,6 +16,8 @@ itg3200-y := itg3200_core.o
itg3200-$(CONFIG_IIO_BUFFER) += itg3200_buffer.o
obj-$(CONFIG_ITG3200) += itg3200.o
obj-$(CONFIG_IIO_SSP_SENSORS_COMMONS) += ssp_gyro_sensor.o
obj-$(CONFIG_IIO_ST_GYRO_3AXIS) += st_gyro.o
st_gyro-y := st_gyro_core.o
st_gyro-$(CONFIG_IIO_BUFFER) += st_gyro_buffer.o
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -14,3 +14,5 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
obj-y += inv_mpu6050/
obj-$(CONFIG_KMX61) += kmx61.o
......@@ -7,6 +7,7 @@ config INV_MPU6050_IIO
depends on I2C && SYSFS
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select I2C_MUX
help
This driver supports the Invensense MPU6050 devices.
This driver can also support MPU6500 in MPU6050 compatibility mode
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册