]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
iio: Add sensor wake_up support
authorErik Lilliebjerg <elilliebjerg@nvidia.com>
Fri, 22 May 2015 13:43:43 +0000 (06:43 -0700)
committerRobert Collins <rcollins@nvidia.com>
Mon, 8 Jun 2015 21:05:22 +0000 (14:05 -0700)
- Add wake_up sensor type support.
- Remove IIO dependencies from light and proximity headers for portability.
- Add driver documentation.
- Add ICM20628 compatibility label.
- Add global disable allowing no driver interaction with device.
- Fix interpolation 64-bit divide in light and proximity modules.
- Fix CM32180 device parameter table.
- Fix IQS2X6 Kconfig label.

Bug 1646541

Change-Id: Ice6d2b435c7f60256ef36601f7c7aaefbcbc53b3
Signed-off-by: Erik Lilliebjerg <elilliebjerg@nvidia.com>
Reviewed-on: http://git-master/r/746199
(cherry picked from commit 82bd8d8464c2539577e5987f69271afeddce37ec)
Reviewed-on: http://git-master/r/754562
GVS: Gerrit_Virtual_Submit
Reviewed-by: Robert Collins <rcollins@nvidia.com>
26 files changed:
Documentation/devicetree/bindings/iio/ak8963c-compass.txt
Documentation/devicetree/bindings/iio/bmp280-pressure.txt
Documentation/devicetree/bindings/iio/cm3217-als.txt
Documentation/devicetree/bindings/iio/cm3218x-als.txt [new file with mode: 0644]
Documentation/devicetree/bindings/iio/icm20628-gyro.txt
Documentation/devicetree/bindings/iio/iqs253-ps.txt
Documentation/devicetree/bindings/iio/jsa1127-als-txt
Documentation/devicetree/bindings/iio/ltr659-ps.txt
drivers/iio/common/nvs/nvs_iio.c
drivers/iio/common/nvs/nvs_light.c
drivers/iio/common/nvs/nvs_of_dt.c
drivers/iio/common/nvs/nvs_proximity.c
drivers/iio/imu/nvi_mpu/nvi.c
drivers/iio/light/nvs_cm3217.c
drivers/iio/light/nvs_cm3218.c
drivers/iio/light/nvs_isl2902x.c
drivers/iio/light/nvs_jsa1127.c
drivers/iio/light/nvs_ltr659.c
drivers/iio/light/nvs_max4400x.c
drivers/iio/magnetometer/nvi_ak89xx.c
drivers/iio/pressure/nvi_bmpX80.c
drivers/iio/proximity/Kconfig
drivers/iio/proximity/nvs_iqs2x3.c
include/linux/nvs.h
include/linux/nvs_light.h
include/linux/nvs_proximity.h

index da486db4dd53ca9c0acfe66545324b87204531e6..b197b9ede9a0f065029b5b77d5affe4b2e1f7231 100644 (file)
@@ -1,18 +1,52 @@
-* AKM 8963C Compass sensor
+* AKM 8963/8975/09911 compass sensor
+
+nvi_ (NVI = NVidia/Invensense) drivers use the NVidia Sensor (NVS) framework.
+See the nvs.txt documentation for NVS DT capabilities.
+The nvi_ak89xx compass sensor driver supports the AK8963, AK8975, and
+AK09911 devices as stand-alone or behind an Invensense MPU.
 
 Required properties:
-- compatible: must be "ak,ak89xx"
+- compatible: Device or generic name.
+             Supported device names:
+             - ak,ak89xx
+             - ak,ak8963
+             - ak,ak8975
+             - ak,ak09911
+  Note: If the part is known and is populated, then it can be specified:
+       Example: compatible = "ak,ak8963";
+       When specifying a device this way, the driver will assume this specific
+       device is populated during system boot and will not verify its
+       existence.  If, however, the device is unknown or may not be populated,
+       then the label, ak89xx, (Example: compatible = "ak,ak89xx";),
+       must be used.  This tells the driver to find which device is used.  If
+       the device is not found, the driver will unload itself.  This requires
+       regulators to be setup correctly for the probe function.
 - reg: i2c address of the device. It should be 0x0C or 0x0D.
+  Note: the AKM09911 also supports I2C addresses 0x0E and 0x0F.
 
 Optional properties:
-- magnetic_field_disable: Setting this property to <1> will disable this
-                          driver: The driver will unload after this property is
-                         detected.
+- status: set to "ok" or "okay" for normal operation.  Set to anything else
+         to unload the driver without ever communicating with the device.
+  Note: The "anything else" above is typically "disabled".
+       Since the driver will unload without communicating with the device, the
+       device will be left in its POR state.
+- magnetic_field_disable: Setting this property to <1> will disable the device
+                          and unload the driver.
+- vdd-supply: regulator supply for the chip
+- vid-supply: regulator supply for the chip
+  Note: These are required if the driver is to control the regulators.
 - magnetic_field_matrix:  Orientation matrix for this device.
+- nvi_config: This configures the device's I2C connection.
+              The string options are: auto
+                                     mpu
+                                     host
+             auto = the driver will auto detect the connection.
+             mpu = the device is connected to an Invensense auxilary bus.
+             host = the device is connected to the host AP.
+             If this property is not defined, auto will be used.
 
 Example:
-
-       ak8963c@0d {
+       ak89xx@0d {
                compatible = "ak,ak89xx";
                 reg = <0x0d>;
                 magnetic_field_matrix = [ff 00 00 00 ff 00 00 00 01];
index 14e18267e8a50702b7dcc375f119f769e7ed52b3..0d5820106675331ba8a273a260740516051c7ccb 100644 (file)
@@ -1,12 +1,46 @@
-* Bosch BMP-280 pressure sensor
+* Bosch BMP 180/280 pressure sensor
+
+nvi_ (NVI = NVidia/Invensense) drivers use the NVidia Sensor (NVS) framework.
+See the nvs.txt documentation for NVS DT capabilities.
+The nvi_bmpX80 pressure sensor driver supports the BMP180 and BMP280 devices
+as stand-alone or behind an Invensense MPU.
+If the part is known and is populated, then it can be specified in the DT:
+Example: bmp280@77.
+By specifying a device this way, the driver will assume this specific device
+is populated during system boot and will not verify its existence. If, however,
+the device is unknown or may not be populated, then the label, ak89xx,
+(e.g. bmpX80@77), must be used.  This tells the driver to find which device is
+used.  If the device is not found, the driver will unload itself.  This also
+requires that regulators be setup correctly for the probe function.
 
 Required properties:
-- compatible: must be "bmp,bmpX80"
+- compatible: Device or generic name.
+             Supported names:
+             - bmp,bmpX80
+             - bmp,bmp180
+             - bmp,bmp280
+  Note: If the part is known and is populated, then it can be specified:
+       Example: compatible = "bmp,bmp280";
+       When specifying a device this way, the driver will assume this specific
+       device is populated during system boot and will not verify its
+       existence.  If, however, the device is unknown or may not be populated,
+       then the label, bmpX80, (Example: compatible = "bmp,bmpX80";),
+       must be used.  This tells the driver to find which device is used.  If
+       the device is not found, the driver will unload itself.  This requires
+       regulators to be setup correctly for the probe function.
 - reg: i2c address of the device. It should be 0x76 or 0x77.
 
 Optional properties:
-- pressure_disable: Setting this property to <1> will disable this driver:
-                    The driver will unload after this property is detected.
+- status: set to "ok" or "okay" for normal operation.  Set to anything else
+         to unload the driver without ever communicating with the device.
+  Note: The "anything else" above is typically "disabled".
+       Since the driver will unload without communicating with the device, the
+       device will be left in its POR state.
+- pressure_disable: Setting this property to <1> will disable the device and
+                   unload the driver.
+- vdd-supply: regulator supply for the chip
+- vddio-supply: regulator supply for the chip
+  Note: These are required if the driver is to control the regulators.
 - nvi_config: This configures the device's I2C connection.
               The string options are: auto
                                      mpu
@@ -17,8 +51,7 @@ Optional properties:
              If this property is not defined, auto will be used.
 
 Example:
-
-       bmp280@77 {
+       bmpX80@77 {
                 compatible = "bmp,bmpX80";
                 reg = <0x77>;
         };
index e708247ee7a5eb8a42d8183647aad57b8d3a0b56..ba796e74aae617e4adbee155cc47aabc0a64f41f 100644 (file)
@@ -1,13 +1,25 @@
 * Capella CM3217 ambient light sensor
 
+nvs_ drivers use the NVidia Sensor (NVS) framework.
+See the nvs.txt documentation for NVS DT capabilities.
+
 Required properties:
 - compatible: must be "capella,cm3217"
 - reg: i2c address of the device. It should be 0x10.
-- vdd-supply: regulator supply for the chip
 
 Optional properties:
-- light_disable: Setting this property to <1> will disable this driver:
-                 The driver will unload after this property is detected.
+- status: set to "ok" or "okay" for normal operation.  Set to anything else
+         to unload the driver without ever communicating with the device.
+  Note: The "anything else" above is typically "disabled".
+       Since the driver will unload without communicating with the device, the
+       device will be left in its POR state.
+       This device's POR comes up in an operational mode and will draw power.
+       If it is desired to unload the driver leaving the device in a low power
+       sleep state, then use the individual sensor disable mechanism below.
+- light_disable: Setting this property to <1> will disable the device and
+                 unload the driver.
+- vdd-supply: regulator supply for the chip
+  Note: This is required if the driver is to control the regulator.
 
 Example:
        cm3217@10 {
diff --git a/Documentation/devicetree/bindings/iio/cm3218x-als.txt b/Documentation/devicetree/bindings/iio/cm3218x-als.txt
new file mode 100644 (file)
index 0000000..5a013b2
--- /dev/null
@@ -0,0 +1,49 @@
+* Capella CM3218/CM32180/CM32181 ambient light sensor
+
+nvs_ drivers use the NVidia Sensor (NVS) framework.
+See the nvs.txt documentation for NVS DT capabilities.
+The nvs_cm3218 ALS sensor driver supports the CM3218, CM32180, and CM32181
+devices.
+
+Required properties:
+- compatible: Device or generic name.
+             Supported device names:
+             - capella,cm3218x
+             - capella,cm3218
+             - capella,cm32180
+             - capella,cm32181
+  Note: If the part is known and is populated, then it can be specified:
+       Example: compatible = "capella,cm32181";
+       When specifying a device this way, the driver will assume this specific
+       device is populated during system boot and will not verify its
+       existence.  If, however, the device is unknown or may not be populated,
+       then the label, cm3218x, (Example: compatible = "capella,cm3218x";),
+       must be used.  This tells the driver to find which device is used.  If
+       the device is not found, the driver will unload itself.  This requires
+       regulators to be setup correctly for the probe function.
+- reg: i2c address of the device. It should be 0x10 or 0x48.
+
+Optional properties:
+- status: set to "ok" or "okay" for normal operation.  Set to anything else
+         to unload the driver without ever communicating with the device.
+  Note: The "anything else" above is typically "disabled".
+       Since the driver will unload without communicating with the device, the
+       device will be left in its POR state.
+       This device's POR comes up in an operational mode and will draw power.
+       If it is desired to unload the driver leaving the device in a low power
+       sleep state, then use the individual sensor disable mechanism below.
+- light_disable: Setting this property to <1> will disable the device and
+                 unload the driver.
+- vdd-supply: regulator supply for the chip
+  Note: This is required if the driver is to control the regulator.
+- interrupt-parent:  GPIO number
+- interrupts:  GPIO macro
+  Note: The driver will operate in poll mode if an interrupt is not specified.
+
+Example:
+       cm3218x@48 {
+               compatible = "capella,cm3218x";
+               reg = <0x10>;
+               vdd-supply = <&palmas_smps9>;
+       };
+
index a8421d6ab3e5d46726fc69fad18d5fa0a206be02..277376235d4f36e3761208b1fc8bf9f2590f7e34 100644 (file)
@@ -1,12 +1,39 @@
-* Invensense ICM-20628 Gyro/Accelerometer sensor
+* Invensense ICM-20628 and MPUxxxx Gyro/Accelerometer(/compass) sensors
+
+This driver uses the NVidia Sensor (NVS) framework.
+See the nvs.txt documentation for NVS DT capabilities.
+The nvi sensor driver supports the ICM, MPU6xxx and MPU9xxx devices.
 
 Required properties:
-- compatible: must be "invensense,mpu6xxx"
+- compatible: Device or generic name.
+             Supported device names:
+             - invensense,mpu6xxx
+             - invensense,mpu6050
+             - invensense,mpu6500
+             - invensense,mpu6515
+             - invensense,mpu9150
+             - invensense,mpu9250
+             - invensense,mpu9350
+             - invensense,icm20628
+  Note: If the part is known and is populated, then it can be specified:
+       Example: compatible = "invensense,icm20628";
+       When specifying a device this way, the driver will assume this specific
+       device is populated during system boot and will not verify its
+       existence.  If, however, the device is unknown or may not be populated,
+       then the label, mpu6xxx, (Example: compatible = "invensense,mpu6xxx";),
+       must be used.  This tells the driver to find which device is used.  If
+       the device is not found, the driver will unload itself.  This requires
+       regulators to be setup correctly for the probe function.
 - reg: i2c address of the device. It should be 0x68 or 0x69.
 - interrupt-parent:  GPIO number
 - interrupts:  GPIO macro
 
 Optional properties:
+- status: set to "ok" or "okay" for normal operation.  Set to anything else
+         to unload the driver without ever communicating with the device.
+  Note: The "anything else" above is typically "disabled".
+       Since the driver will unload without communicating with the device, the
+       device will be left in its POR state.
 - accelerometer_disable: Setting this property to <1> will disable the
                          accelerometer.
 - gyroscope_disable: Setting this property to <1> will disable the gyroscope.
@@ -17,12 +44,13 @@ Optional properties:
        accelerometer_disable = <1>;
        gyroscope_disable = <1>;
        gyro_temp_disable = <1>;
-
+- vdd-supply: regulator supply for the chip
+- vlogic-supply: regulator supply for the chip
+  Note: These are required if the driver is to control the regulators.
 - accelerometer_matrix:  Orientation matrix for this device.
 - gyroscope_matrix:  Orientation matrix for this device.
 
 Example:
-
        icm20628@69 {
                compatible = "invensense,mpu6xxx";
                 reg = <0x69>;
index 43e4537c3d44ad3dc845efc8df957ff0f4fb5fdb..54aa694d12561792bc80ecb751f085454e14f866 100644 (file)
@@ -1,5 +1,7 @@
 * IQS2x3 proximity sensor
 
+nvs_ drivers use the NVidia Sensor (NVS) framework.
+See the nvs.txt documentation for NVS DT capabilities.
 The nvs_iqs2x3 proximity sensor driver supports the IQS253 and IQS263 devices.
 These two parts are not register compatible and therefore should be specified
 in the device tree.  Example: iqs263@44.  By specifying a device this way, the
@@ -11,9 +13,23 @@ device is used.  If the device is not found, the driver will unload itself.
 This also requires that regulators be setup correctly for the probe function.
 
 Required properties:
-- compatible: must be "azoteq,iqs2x3"
+- compatible: Device or generic name.
+             Supported device names:
+             - azoteq,iqs2x3
+             - azoteq,iqs253
+             - azoteq,iqs263
+  Note: If the part is known and is populated, then it can be specified:
+       Example: compatible = "azoteq,iqs263";
+       When specifying a device this way, the driver will assume this specific
+       device is populated during system boot and will not verify its
+       existence.  If, however, the device is unknown or may not be populated,
+       then the label, iqs2x3, (Example: compatible = "azoteq,iqs2x3";),
+       must be used.  This tells the driver to find which device is used.  If
+       the device is not found, the driver will unload itself.  This requires
+       regulators to be setup correctly for the probe function.
 - reg: i2c address of the device. It is one of 0x44-0x47.
-- gpio_rdy: gpio to be used for the I2C handshake with the sensor.
+- gpio_rdy: GPIO to be used for the I2C handshake with the sensor.
+  Note: the gpio_rdy GPIO will be used as an interrupt also.
 
 The IQS devices have a very versatile register set.  So much so that the entire
 register set values can be different among platforms.  Because of this, the way
@@ -32,17 +48,17 @@ mask for the first byte 0x12, and 0xFF is the mask for the second byte 0x34.
 The entry for this example if the register is, say, 0x56, would be:
 02, 56, 12, 34, 1E, FF
 
-Note that the IQS has a funky register set in that each register has its own
-register length.  The reason LENGTH is still used is that maybe only the first
-few bytes of a register are to be written.  For example, a register that is 20
-bytes long can get by with defining, say 4 for LENGTH, and only the first 4
-bytes will be written.
+The IQS has a funky register set in that each register has its own register
+length.  The reason LENGTH is still used is that maybe only the first few bytes
+of a register are to be written.  For example, a register that is 20 bytes long
+can get by with defining, say 4 for LENGTH, and only the first 4 bytes will be
+written.
 
 The DT labeling mechanism is based on the part number and the command to be
-accomplished. Currently there are only two commands: initialization and enable.
-For each label, a "_?" is appended where ? is a decimal number starting at 0.
-Note that driver will put the entries in the sequence defined by ? and not by
-the order defined in the DT.
+accomplished. Currently there are four commands: initialization, enable,
+disable, and event.  For each label, a "_?" is appended where ? is a decimal
+number starting at 0.  Note the driver will put the entries in the sequence
+defined by ? and not by the order defined in the DT.
 An example for initialization of the IQS263 part in the DT is as follows:
        263init_0 = [05 09 40 03 00 01 03 FF FF FF FF FF]; // 5 bytes to reg 9
        263init_1 = [01 0D 09 FF]; // 1 byte written to register 0x0D
@@ -65,6 +81,19 @@ Here is a DT example of the enable commands for both sensors:
        263en_touch_0 = [01 09 10 18];  // 1 byte written to register 0x09
        263en_touch_1 = [FF 00];        // write flush.  See description below.
        263en_touch_2 = [01 09 08 18];  // 1 byte written to register 0x09
+Here are the possible disable command labels:
+       263dis_prox_?
+       263dis_touch_?
+       253dis_prox_?
+       253dis_touch_?
+The disable commands do not need to write to the registers to put the device to
+sleep.  When the driver sees that all the sensors are disabled it will handle
+the global sleep.
+The event command allows any necessary action whenever the device receives an
+event:
+       263event_?
+       253event_?
+If partial ATI is enabled, the driver will automatically handle the reseeding.
 
 Due to the IQS device's design for communicating with the device, each entry,
 which represents an I2C transaction, is actually stacked so that the entire
@@ -75,20 +104,25 @@ can be set to FF.  This tells the driver's byte stream parsing engine to
 execute the I2C transactions thus far and if a millisecond delay is to also be
 done, then the following byte contains the number of milliseconds to wait,
 otherwise the following byte's value is 0.
+The FF does NOT need to be entered at the end of a byte stream command.  The
+driver's byte stream parsing engine will automatically execute the I2C
+transactions.
+It is strongly recommended to not use the flush write within an event command
+byte stream.
 
 FYI, internally to the driver, the byte stream terminates when LENGTH is 0.
 This is handled automatically by the driver's DT parsing, but is an FYI so that
-0 is never used for LENGTH.  Also note that the driver's DT parsing engine has
-error checking and will exit with an error of "ERR: NOMEM @ %s" where %s will
-be the DT label where things went south.  The error can be due to truly out of
-buffer memory to non-existent register or incorrect register length.
-Once the driver has loaded, a debug feature that will dump the parsed byte
-stream can be done by doing the following at the device's sysfs directory in an
-adb terminal prompt:
+0 is never used for LENGTH.
+The driver's DT parsing engine has error checking and will exit with an error
+of "ERR: NOMEM @ %s" where %s will be the DT label where things went south.
+The error can be due to truly out of buffer memory to non-existent register or
+incorrect register length.  Once the driver has loaded, a debug feature that
+will dump the parsed byte stream can be done by doing the following at the
+device's sysfs directory in an adb terminal prompt:
 $echo 10 > nvs
 $cat nvs
 The results will be something like:
-       IQS driver v. 4
+       IQS driver v. 6
        os_options=0
        stream_mode=0
        watchdog_timeout_ms=30000
@@ -116,12 +150,35 @@ The results will be something like:
        flush write and mdelay=0
        len=1 reg=9 data/mask=8/18
        IQS253 initialization:
+Also, a register dump can be done:
+$echo 4 > nvs
+$cat nvs
+During the tuning process, a debug feature can write a byte to a register:
+$echo 0xXXYYZZ1D > nvs
+where XX = the register
+      YY = the register offset
+      ZZ = the byte value
+Other driver debug commands:
+$echo 0x??1C > nvs
+writes ?? to the gpio_sar GPIO.
+$echo 0x??1B > nvs
+writes ?? to the gpio_rdy GPIO.
+$echo 0x1A > nvs
+switches the gpio_rdy GPIO to input.
 
-Note that in the case the part populated could be either IQS253 or IQS263, both
-the 253 and 263 commands can be defined in the DT.  The driver will use the one
+In the case the part populated could be either IQS253 or IQS263, both the 253
+and 263 commands can be defined in the DT.  The driver will use the one
 according to the part identified.
 
 Optional properties:
+- status: set to "ok" or "okay" for normal operation.  Set to anything else
+         to unload the driver without ever communicating with the device.
+  Note: The "anything else" above is typically "disabled".
+       Since the driver will unload without communicating with the device, the
+       device will be left in its POR state.
+       This device's POR comes up in an operational mode and will draw power.
+       If it is desired to unload the driver leaving the device in a low power
+       sleep state, then use the individual sensor disable mechanism below.
 - SAR_proximity_disable: Setting this property to <1> will disable the
                          SAR proximity.
 - touch_proximity_disable: Setting this property to <1> will disable the
@@ -130,7 +187,9 @@ Optional properties:
         must be disabled:
        SAR_proximity_disable = <1>;
        touch_proximity_disable = <1>;
-- gpio_sar: gpio to be used for sending proximity event for SAR sensor.
+- vddhi-supply: regulator supply for the chip
+  Note: This is required if the driver is to control the regulator.
+- gpio_sar: GPIO to be used for sending proximity event for SAR sensor.
   Note: The gpio_sar define is not required if the following is true:
        - The device's PO pin is wired to the device requiring the SAR event.
        - The assert level is high.
@@ -146,17 +205,18 @@ Optional properties:
        os_options is > 0, the OS will be tricked into thinking is has control.
        In other words, when os_options is 0 (the default), the device will
        always be enabled.
-- stream_mode: The device always triggers an interrupt on every read.
+- stream_mode: The device triggers an interrupt on every device data cycle.
   Note: As mentioned above, the IQS devices have an, um, interesting mechanism
         for communication where there is a small window of time where the
        device will respond to I2C commands (the reason for I2C transaction
        stacking).  When stream mode is disabled, the driver uses a combination
        of disabling/enabling the interrupt, which also doubles in forcing the
-       communication window, and reading the device's status and data.  The
-       mechanism allows the device to not interrupt the AP unless an event has
-       occured, thereby saving power.  However, depending on how the device is
-       configured by the DT commands, it may be desirable to disable this
-       feature and stream the data instead.
+       communication window, and reading the device's status and data via
+       stream and event modes.  The mechanism allows the device to not
+       interrupt the AP unless an event has occured, thereby saving power.
+       However, depending on how the device is configured by the DT commands,
+       it may be desirable to disable this feature and continually stream the
+       data instead.
 - watchdog_timeout_ms: When streaming mode is disabled, a watchdog can
                       periodically stream the data to confirm the device's
                       status.
@@ -190,8 +250,6 @@ And finally, an example:
                gpio_rdy = <&gpio TEGRA_GPIO(A, 1) GPIO_ACTIVE_LOW>;
                gpio_sar = <&gpio TEGRA_GPIO(V, 5) GPIO_ACTIVE_LOW>;
                sar_assert_polarity = <0>;
-               SAR_proximity_no_suspend = <1>;
-               touch_proximity_no_suspend = <1>;
                os_options = <0>;
                263init_0 = [05 09 40 03 00 01 03 FF FF FF FF FF];
                263init_1 = [01 0D 09 FF];
index 89dcacf7fd5bf44b0dbd5a52ce44b65965d2e5c6..055852b8c728fa1ad21742d7bf294a9b4dee8af5 100644 (file)
@@ -1,12 +1,22 @@
 * Soltech JSA-1127 ambient light sensor
 
+nvs_ drivers use the NVidia Sensor (NVS) framework.
+See the nvs.txt documentation for NVS DT capabilities.
+
 Required properties:
 - compatible: must be "solteamopto,jsa1127"
-- reg: i2c address of the device. It should be 0x39.
+- reg: i2c address of the device. It can be 0x29, 0x39 or 0x44.
 
 Optional properties:
-- light_disable: Setting this property to <1> will disable this driver:
-                 The driver will unload after this property is detected.
+- status: set to "ok" or "okay" for normal operation.  Set to anything else
+         to unload the driver without ever communicating with the device.
+  Note: The "anything else" above is typically "disabled".
+       Since the driver will unload without communicating with the device, the
+       device will be left in its POR state.
+- light_disable: Setting this property to <1> will disable the device and
+                unload the driver.
+- vdd-supply: regulator supply for the chip
+  Note: This is required if the driver is to control the regulator.
 Format:        light_mode_settingname
 Where: 'light' refers to the light sensor classification
        'mode' refers to data collection mode:
index ed4d8f6f00fe7af8a09e40624e380a88808c8f31..23ea4155b74d6a84a0c583224c194498250ba2c1 100644 (file)
@@ -1,12 +1,41 @@
-* LTR659 proximity sensor
+* LTR 558/659 ALS/proximity sensor
+
+nvs_ drivers use the NVidia Sensor (NVS) framework.
+See the nvs.txt documentation for NVS DT capabilities.
+The nvs_ltr659 ALS/proximity sensor driver supports the LTR558 and LTR659
+devices.
+If the part is known and is populated, then it can be specified in the DT:
+Example: ltr659@23.
+By specifying a device this way, the driver will assume this specific device
+is populated during system boot and will not verify its existence. If, however,
+the device is unknown or may not be populated, then the label, ltrX5X,
+(e.g. ltrX5X@23), must be used.  This tells the driver to find which device is
+used.  If the device is not found, the driver will unload itself.  This also
+requires that regulators be setup correctly for the probe function.
 
 Required properties:
-- compatible: must be "liteon,ltrX5X"
+- compatible: Device or generic name.
+             Supported device names:
+             - liteon,ltrX5X
+             - liteon,ltr558als
+             - liteon,ltr659ps
+  Note: If the part is known and is populated, then it can be specified:
+       Example: compatible = "liteon,ltr659ps";
+       When specifying a device this way, the driver will assume this specific
+       device is populated during system boot and will not verify its
+       existence.  If, however, the device is unknown or may not be populated,
+       then the label, ltrX5X, (Example: compatible = "liteon,ltrX5X";),
+       must be used.  This tells the driver to find which device is used.  If
+       the device is not found, the driver will unload itself.  This requires
+       regulators to be setup correctly for the probe function.
 - reg: i2c address of the device. It is 0x23.
-- vdd-supply: regulator supply for chip
-- vled-supply: regulator supply for led anode.
 
 Optional properties:
+- status: set to "ok" or "okay" for normal operation.  Set to anything else
+         to unload the driver without ever communicating with the device.
+  Note: The "anything else" above is typically "disabled".
+       Since the driver will unload without communicating with the device, the
+       device will be left in its POR state.
 - light_disable: Setting this property to <1> will disable the light sensor.
 - proximity_disable: Setting this property to <1> will disable the proximity
                      sensor.
@@ -14,6 +43,9 @@ Optional properties:
         entire device so that the driver unloads, all sensors must be disabled:
        light_disable = <1>;
        proximity_disable = <1>;
+- vdd-supply: regulator supply for chip
+- vled-supply: regulator supply for led anode.
+  Note: These are required if the driver is to control the regulators.
 
 Example:
 
index b43b43a69358dcb953c2bef48613a8ee08ab8fe3..72c97e8047cd3e9eff5ee526df934cee9b76c5a2 100644 (file)
@@ -349,7 +349,6 @@ static ssize_t nvs_dbg_cfg(struct iio_dev *indio_dev, char *buf)
        t += sprintf(buf + t, "snsr_id=%d\n", st->cfg->snsr_id);
        t += sprintf(buf + t, "timestamp_sz=%d\n", st->cfg->timestamp_sz);
        t += sprintf(buf + t, "snsr_data_n=%d\n", st->cfg->snsr_data_n);
-       t += sprintf(buf + t, "no_suspend=%x\n", st->cfg->no_suspend);
        t += sprintf(buf + t, "kbuf_sz=%d\n", st->cfg->kbuf_sz);
        t += sprintf(buf + t, "ch_n=%u\n", st->cfg->ch_n);
        t += sprintf(buf + t, "ch_sz=%d\n", st->cfg->ch_sz);
@@ -1460,7 +1459,7 @@ static int nvs_suspend(void *handle)
 
        mutex_lock(&indio_dev->mlock);
        st->suspend = true;
-       if (!st->cfg->no_suspend) {
+       if (!(st->cfg->flags & SENSOR_FLAG_WAKE_UP)) {
                ret = st->fn_dev->enable(st->client, st->cfg->snsr_id, -1);
                if (ret > 0)
                        ret = st->fn_dev->enable(st->client,
index dce9cdd443ca0e5e0ec6057b64cfa35137cb6ee1..0e6061a13d8dd2d04493a27b412ced83baad962c 100644 (file)
@@ -189,7 +189,13 @@ static u32 nvs_light_interpolate(int x1, s64 x2, int x3, int y1, int y3)
                return (u32)x2;
 
        dividend = (x2 - x1) * (y3 - y1);
-       do_div(dividend, divisor);
+       if (dividend < 0) {
+               dividend = abs64(dividend);
+               do_div(dividend, divisor);
+               dividend = 0 - dividend;
+       } else {
+               do_div(dividend, divisor);
+       }
        dividend += y1;
        if (dividend < 0)
                dividend = 0;
@@ -337,7 +343,7 @@ int nvs_light_read(struct nvs_light *nl)
                                                        nl->cfg->cal_hi);
                }
                /* report lux */
-               nl->handler(nl->nvs_data, &nl->lux, nl->timestamp_report);
+               nl->handler(nl->nvs_st, &nl->lux, nl->timestamp_report);
                if ((nl->thresholds_valid) && !nl->report) {
                        /* calculate low threshold */
                        calc = (s64)nl->hw;
@@ -431,7 +437,7 @@ int nvs_light_of_dt(struct nvs_light *nl, const struct device_node *np,
        int ret_t = -EINVAL;
 
        if (nl->cfg)
-               nl->cfg->flags = SENSOR_FLAG_ON_CHANGE_MODE;
+               nl->cfg->flags |= SENSOR_FLAG_ON_CHANGE_MODE;
        if (np == NULL)
                return -EINVAL;
 
index 89b05abf82d658fe8b24820602e34f8007d19c08..6fc12ba7b0d411b701241a85f22b29328dfd3727 100644 (file)
@@ -30,11 +30,25 @@ int nvs_of_dt(const struct device_node *np, struct sensor_cfg *cfg,
        int lenp;
        int ret;
 
-       if (np == NULL || cfg == NULL)
+       if (np == NULL)
+               return -EINVAL;
+
+       if (!of_device_is_available(np))
+               return -ENODEV;
+
+       if (cfg == NULL)
                return -EINVAL;
 
        if (dev_name == NULL)
                dev_name = cfg->name;
+       ret = sprintf(str, "%s_disable", dev_name);
+       if (ret > 0) {
+               ret = of_property_read_u32(np, str, (u32 *)&i);
+               if (!ret) {
+                       if (i)
+                               cfg->snsr_id = -1;
+               }
+       }
        ret = sprintf(str, "%s_float_significance", dev_name);
        if (ret > 0) {
                if (!(of_property_read_string((struct device_node *)np,
@@ -48,22 +62,13 @@ int nvs_of_dt(const struct device_node *np, struct sensor_cfg *cfg,
                        }
                }
        }
-       ret = sprintf(str, "%s_no_suspend", dev_name);
-       if (ret > 0) {
-               ret = of_property_read_u32(np, str, (u32 *)&i);
-               if (!ret) {
-                       if (i)
-                               cfg->no_suspend = true;
-                       else
-                               cfg->no_suspend = false;
-               }
-       }
-       ret = sprintf(str, "%s_disable", dev_name);
+       ret = sprintf(str, "%s_flags", dev_name);
        if (ret > 0) {
                ret = of_property_read_u32(np, str, (u32 *)&i);
                if (!ret) {
-                       if (i)
-                               cfg->snsr_id = -1;
+                       cfg->flags &= SENSOR_FLAG_NO_CFG_MASK;
+                       i &= ~SENSOR_FLAG_NO_CFG_MASK;
+                       cfg->flags |= i;
                }
        }
        ret = sprintf(str, "%s_kbuffer_size", dev_name);
@@ -99,9 +104,6 @@ int nvs_of_dt(const struct device_node *np, struct sensor_cfg *cfg,
        ret = sprintf(str, "%s_fifo_reserved_event_count", dev_name);
        if (ret > 0)
                of_property_read_u32(np, str, (u32 *)&cfg->fifo_max_evnt_cnt);
-       ret = sprintf(str, "%s_flags", dev_name);
-       if (ret > 0)
-               of_property_read_u32(np, str, (u32 *)&cfg->flags);
        ret = sprintf(str, "%s_matrix", dev_name);
        if (ret > 0) {
                charp = of_get_property(np, str, &lenp);
index 403c42e0a83d4a88faceb4cac1a29996afafb514..433926a4aac33f668e6b6a5bb70dc4823b002fe7 100644 (file)
@@ -166,7 +166,13 @@ static void nvs_proximity_interpolate(int x1, s64 x2, int x3,
        }
 
        dividend = (x2 - x1) * (y3 - y1);
-       do_div(dividend, divisor);
+       if (dividend < 0) {
+               dividend = abs64(dividend);
+               do_div(dividend, divisor);
+               dividend = 0 - dividend;
+       } else {
+               do_div(dividend, divisor);
+       }
        dividend += y1;
        if (dividend < 0)
                dividend = 0;
@@ -249,7 +255,7 @@ int nvs_proximity_read(struct nvs_proximity *np)
                if (np->report && report_delay_min) {
                        np->report--;
                        np->timestamp_report = np->timestamp;
-                       np->handler(np->nvs_data, &np->proximity,
+                       np->handler(np->nvs_st, &np->proximity,
                                    np->timestamp_report);
                        ret = RET_HW_UPDATE;
                }
@@ -326,7 +332,7 @@ int nvs_proximity_read(struct nvs_proximity *np)
                if (np->report && report_delay_min) {
                        np->report--;
                        np->timestamp_report = np->timestamp;
-                       np->handler(np->nvs_data, &np->proximity,
+                       np->handler(np->nvs_st, &np->proximity,
                                    np->timestamp_report);
                        ret = RET_HW_UPDATE;
                }
@@ -381,7 +387,7 @@ int nvs_proximity_read(struct nvs_proximity *np)
                                                          np->cfg->cal_hi);
                        }
                        /* report proximity */
-                       np->handler(np->nvs_data, &np->proximity,
+                       np->handler(np->nvs_st, &np->proximity,
                                    np->timestamp_report);
                        if ((np->thresholds_valid) && !np->report) {
                                /* calculate low threshold */
@@ -463,7 +469,7 @@ int nvs_proximity_of_dt(struct nvs_proximity *np, const struct device_node *dn,
        int ret;
 
        if (np->cfg)
-               np->cfg->flags = SENSOR_FLAG_ON_CHANGE_MODE;
+               np->cfg->flags |= SENSOR_FLAG_ON_CHANGE_MODE;
        if (dn == NULL)
                return -EINVAL;
 
index d8ba16e0819021b840a79301007f6218e7a7d228..c660a9e1a1eba3725e261525232409c9160238fb 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "nvi.h"
 
-#define NVI_DRIVER_VERSION             (208)
+#define NVI_DRIVER_VERSION             (209)
 #define NVI_NAME                       "mpu6xxx"
 #define NVI_NAME_MPU6050               "MPU6050"
 #define NVI_NAME_MPU6500               "MPU6500"
@@ -147,13 +147,15 @@ int nvi_i2c_write(struct nvi_state *st, u16 addr, u16 len, u8 *buf)
 {
        struct i2c_msg msg;
 
-       msg.addr = addr;
-       msg.flags = 0;
-       msg.len = len;
-       msg.buf = buf;
-       if (i2c_transfer(st->i2c->adapter, &msg, 1) != 1) {
-               nvi_err(st);
-               return -EIO;
+       if (addr) {
+               msg.addr = addr;
+               msg.flags = 0;
+               msg.len = len;
+               msg.buf = buf;
+               if (i2c_transfer(st->i2c->adapter, &msg, 1) != 1) {
+                       nvi_err(st);
+                       return -EIO;
+               }
        }
 
        return 0;
@@ -198,17 +200,19 @@ int nvi_i2c_read(struct nvi_state *st, u16 addr, u8 reg, u16 len, u8 *buf)
 {
        struct i2c_msg msg[2];
 
-       msg[0].addr = addr;
-       msg[0].flags = 0;
-       msg[0].len = 1;
-       msg[0].buf = &reg;
-       msg[1].addr = addr;
-       msg[1].flags = I2C_M_RD;
-       msg[1].len = len;
-       msg[1].buf = buf;
-       if (i2c_transfer(st->i2c->adapter, msg, 2) != 2) {
-               nvi_err(st);
-               return -EIO;
+       if (addr) {
+               msg[0].addr = addr;
+               msg[0].flags = 0;
+               msg[0].len = 1;
+               msg[0].buf = &reg;
+               msg[1].addr = addr;
+               msg[1].flags = I2C_M_RD;
+               msg[1].len = len;
+               msg[1].buf = buf;
+               if (i2c_transfer(st->i2c->adapter, msg, 2) != 2) {
+                       nvi_err(st);
+                       return -EIO;
+               }
        }
 
        return 0;
@@ -2646,7 +2650,7 @@ static irqreturn_t nvi_irq_thread(int irq, void *dev_id)
        struct nvi_state *st = (struct nvi_state *)dev_id;
        struct aux_port *ap;
        u16 fifo_count = 0;
-       u16 fifo_sample_size;
+       u16 fifo_sample_size = 0;
        u16 fifo_rd_n;
        u16 fifo_align;
        s64 ts;
@@ -4272,6 +4276,16 @@ static int nvi_id_i2c(struct nvi_state *st, const struct i2c_device_id *id)
 static int nvi_of_dt(struct nvi_state *st, struct device_node *dn)
 {
        u32 tmp;
+       unsigned int i;
+       int ret;
+
+       /* common NVS parameters */
+       for (i = 0; i < DEV_N; i++) {
+               ret = nvs_of_dt(dn, &st->cfg[i], NULL);
+               if (ret == -ENODEV)
+                       /* the entire device has been disabled */
+                       return -ENODEV;
+       }
 
        /* device specific parameters */
        if (!of_property_read_u32(dn, "invensense,standby_en", &tmp)) {
@@ -4327,8 +4341,17 @@ static int nvi_probe(struct i2c_client *client,
        nvi_init_config(st);
        if (client->dev.of_node) {
                ret = nvi_of_dt(st, client->dev.of_node);
-               if (ret)
+               if (ret) {
+                       if (ret == -ENODEV) {
+                               dev_info(&client->dev, "%s DT disabled\n",
+                                        __func__);
+                       } else {
+                               dev_err(&client->dev, "%s _of_dt ERR\n",
+                                       __func__);
+                               ret = -ENODEV;
+                       }
                        goto nvi_probe_err;
+               }
        } else {
                pdata = (struct mpu_platform_data *)
                                                dev_get_platdata(&client->dev);
@@ -4362,12 +4385,6 @@ static int nvi_probe(struct i2c_client *client,
 
        n = 0;
        for (i = 0; i < DEV_N; i++) {
-               /* populate any overrides */
-               ret = nvs_of_dt(client->dev.of_node, &st->cfg[i], NULL);
-               if (ret == -ENODEV)
-                       /* the entire device has been disabled */
-                       goto nvi_probe_err;
-
                ret = st->nvs->probe(&st->nvs_st[i], st, &client->dev,
                                     &nvi_fn_dev, &st->cfg[i]);
                if (!ret) {
@@ -4416,6 +4433,7 @@ static struct i2c_device_id nvi_i2c_device_id[] = {
        { "mpu9250", 0 },
        { "mpu9150", 0 },
        { "mpu9350", 0 },
+       { "icm20628", 0 },
        {}
 };
 
@@ -4429,6 +4447,7 @@ static const struct of_device_id nvi_of_match[] = {
        { .compatible = "invensense,mpu9150", },
        { .compatible = "invensense,mpu9250", },
        { .compatible = "invensense,mpu9350", },
+       { .compatible = "invensense,icm20628", },
        {}
 };
 
index 9dfcb636fd139fdbfb75a68f7373c6d6aef9d7a2..96dc79bc65f21e47b425a1e7775b1d47b7e51a61 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+/* Copyright (c) 2014-2015, NVIDIA CORPORATION.  All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -79,7 +79,7 @@ static struct nvs_light_dynamic cm_nld_tbl[] = {
 struct cm_state {
        struct i2c_client *i2c;
        struct nvs_fn_if *nvs;
-       void *nvs_data;
+       void *nvs_st;
        struct sensor_cfg cfg;
        struct delayed_work dw;
        struct regulator_bulk_data vreg[ARRAY_SIZE(cm_vregs)];
@@ -87,20 +87,16 @@ struct cm_state {
        unsigned int sts;               /* debug flags */
        unsigned int errs;              /* error count */
        unsigned int enabled;           /* enable status */
-       bool iio_ts_en;                 /* use IIO timestamps */
        bool hw_change;                 /* HW changed so drop first sample */
        u8 cmd1;                        /* store for register dump */
        u8 cmd2;                        /* store for register dump */
 };
 
 
-static s64 cm_get_time_ns(struct cm_state *st)
+static s64 cm_get_time_ns(void)
 {
        struct timespec ts;
 
-       if (st->iio_ts_en)
-               return iio_get_time_ns();
-
        ktime_get_ts(&ts);
        return timespec_to_ns(&ts);
 }
@@ -249,7 +245,7 @@ static int cm_rd(struct cm_state *st)
        if (ret)
                return ret;
 
-       ts = cm_get_time_ns(st);
+       ts = cm_get_time_ns();
        if (st->sts & NVS_STS_SPEW_DATA)
                dev_info(&st->i2c->dev,
                         "poll light hw %hu %lld  diff=%d %lldns  index=%u\n",
@@ -265,13 +261,13 @@ static int cm_rd(struct cm_state *st)
 
 static void cm_read(struct cm_state *st)
 {
-       st->nvs->nvs_mutex_lock(st->nvs_data);
+       st->nvs->nvs_mutex_lock(st->nvs_st);
        if (st->enabled) {
                cm_rd(st);
                schedule_delayed_work(&st->dw,
                                    msecs_to_jiffies(st->light.poll_delay_ms));
        }
-       st->nvs->nvs_mutex_unlock(st->nvs_data);
+       st->nvs->nvs_mutex_unlock(st->nvs_st);
 }
 
 static void cm_work(struct work_struct *ws)
@@ -359,8 +355,8 @@ static int cm_suspend(struct device *dev)
        int ret = 0;
 
        st->sts |= NVS_STS_SUSPEND;
-       if (st->nvs && st->nvs_data)
-               ret = st->nvs->suspend(st->nvs_data);
+       if (st->nvs && st->nvs_st)
+               ret = st->nvs->suspend(st->nvs_st);
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s\n", __func__);
        return ret;
@@ -372,8 +368,8 @@ static int cm_resume(struct device *dev)
        struct cm_state *st = i2c_get_clientdata(client);
        int ret = 0;
 
-       if (st->nvs && st->nvs_data)
-               ret = st->nvs->resume(st->nvs_data);
+       if (st->nvs && st->nvs_st)
+               ret = st->nvs->resume(st->nvs_st);
        st->sts &= ~NVS_STS_SUSPEND;
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s\n", __func__);
@@ -387,8 +383,8 @@ static void cm_shutdown(struct i2c_client *client)
        struct cm_state *st = i2c_get_clientdata(client);
 
        st->sts |= NVS_STS_SHUTDOWN;
-       if (st->nvs && st->nvs_data)
-               st->nvs->shutdown(st->nvs_data);
+       if (st->nvs && st->nvs_st)
+               st->nvs->shutdown(st->nvs_st);
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s\n", __func__);
 }
@@ -399,8 +395,8 @@ static int cm_remove(struct i2c_client *client)
 
        if (st != NULL) {
                cm_shutdown(client);
-               if (st->nvs && st->nvs_data)
-                       st->nvs->remove(st->nvs_data);
+               if (st->nvs && st->nvs_st)
+                       st->nvs->remove(st->nvs_st);
                if (st->dw.wq)
                        destroy_workqueue(st->dw.wq);
                cm_pm_exit(st);
@@ -411,8 +407,8 @@ static int cm_remove(struct i2c_client *client)
 
 static struct sensor_cfg cm_cfg_dflt = {
        .name                   = NVS_LIGHT_STRING,
-       .ch_n                   = ARRAY_SIZE(iio_chan_spec_nvs_light),
-       .ch_inf                 = &iio_chan_spec_nvs_light,
+       .ch_n                   = 1,
+       .ch_sz                  = 4,
        .part                   = CM_NAME,
        .vendor                 = CM_VENDOR,
        .version                = CM_LIGHT_VERSION,
@@ -430,6 +426,7 @@ static struct sensor_cfg cm_cfg_dflt = {
        },
        .delay_us_min           = CM_POLL_DLY_MS_MIN * 1000,
        .delay_us_max           = CM_POLL_DLY_MS_MAX * 1000,
+       .flags                  = SENSOR_FLAG_ON_CHANGE_MODE,
        .scale                  = {
                .ival           = CM_LIGHT_SCALE_IVAL,
                .fval           = CM_LIGHT_SCALE_MICRO,
@@ -441,6 +438,7 @@ static struct sensor_cfg cm_cfg_dflt = {
 static int cm_of_dt(struct cm_state *st, struct device_node *dn)
 {
        unsigned int i;
+       int ret;
 
        /* default NVS programmable parameters */
        memcpy(&st->cfg, &cm_cfg_dflt, sizeof(st->cfg));
@@ -448,12 +446,10 @@ static int cm_of_dt(struct cm_state *st, struct device_node *dn)
        st->light.hw_mask = 0xFFFF;
        st->light.nld_tbl = cm_nld_tbl;
        /* device tree parameters */
-       if (dn)
-               /* common NVS IIO programmable parameters */
-               st->iio_ts_en = of_property_read_bool(dn, "iio_timestamps");
-       /* common NVS parameters */
-       nvs_of_dt(dn, &st->cfg, NULL);
-       /* this device supports these programmable parameters */
+       ret = nvs_of_dt(dn, &st->cfg, NULL);
+       if (ret == -ENODEV)
+               return -ENODEV;
+
        if (nvs_light_of_dt(&st->light, dn, NULL)) {
                st->light.nld_i_lo = 0;
                st->light.nld_i_hi = ARRAY_SIZE(cm_nld_tbl) - 1;
@@ -485,8 +481,12 @@ static int cm_probe(struct i2c_client *client,
        st->i2c = client;
        ret = cm_of_dt(st, client->dev.of_node);
        if (ret) {
-               dev_err(&client->dev, "%s _of_dt ERR\n", __func__);
-               ret = -ENODEV;
+               if (ret == -ENODEV) {
+                       dev_info(&client->dev, "%s DT disabled\n", __func__);
+               } else {
+                       dev_err(&client->dev, "%s _of_dt ERR\n", __func__);
+                       ret = -ENODEV;
+               }
                goto cm_probe_exit;
        }
 
@@ -506,7 +506,8 @@ static int cm_probe(struct i2c_client *client,
                goto cm_probe_exit;
        }
 
-       ret = st->nvs->probe(&st->nvs_data, st, &client->dev,
+       st->light.handler = st->nvs->handler;
+       ret = st->nvs->probe(&st->nvs_st, st, &client->dev,
                             &cm_fn_dev, &st->cfg);
        if (ret) {
                dev_err(&client->dev, "%s nvs_probe ERR\n", __func__);
@@ -514,8 +515,7 @@ static int cm_probe(struct i2c_client *client,
                goto cm_probe_exit;
        }
 
-       st->light.nvs_data = st->nvs_data;
-       st->light.handler = st->nvs->handler;
+       st->light.nvs_st = st->nvs_st;
        INIT_DELAYED_WORK(&st->dw, cm_work);
        dev_info(&client->dev, "%s done\n", __func__);
        return 0;
index dbbfa7441c04347004441d3a1ec3ee9fcca852e6..542e3cdc035c76eb28317040164c812186414380 100644 (file)
@@ -44,8 +44,8 @@
 #define CM_LIGHT_VERSION               (1)
 #define CM_LIGHT_SCALE_IVAL            (0)
 #define CM_LIGHT_SCALE_MICRO           (10000)
-#define CM_LIGHT_THRESHOLD_LO          (100)
-#define CM_LIGHT_THRESHOLD_HI          (100)
+#define CM_LIGHT_THRESHOLD_LO          (10)
+#define CM_LIGHT_THRESHOLD_HI          (10)
 #define CM_POLL_DLY_MS_MAX             (4000)
 /* HW registers */
 #define CM_REG_CFG                     (0x00)
@@ -78,17 +78,17 @@ static unsigned short cm_i2c_addrs[] = {
 };
 
 static struct nvs_light_dynamic cm3218_nld_tbl[] = {
-       { {0, 3570},  {233,  959950}, {0, 130000}, 1000, 0x00C0 },
-       { {0, 7140},  {467,  919900}, {0, 130000}, 500,  0x0080 },
-       { {0, 14280}, {935,  839800}, {0, 130000}, 250,  0x0040 },
-       { {0, 28560}, {1871, 679600}, {0, 130000}, 125,  0x0000 }
+       { {0, 3571},  {234,  25485},  {0, 130000}, 1000, 0x08C0 },
+       { {0, 7140},  {467,  919900}, {0, 130000}, 500,  0x0880 },
+       { {0, 14280}, {935,  839800}, {0, 130000}, 250,  0x0840 },
+       { {0, 28570}, {1872, 334950}, {0, 130000}, 125,  0x0800 }
 };
 
 static struct nvs_light_dynamic cm32180_nld_tbl[] = {
-       { {0, 890},  {58,  326150}, {0, 130000}, 1000, 0x00C0 },
-       { {0, 1780}, {116, 652300}, {0, 130000}, 500,  0x0080 },
-       { {0, 3560}, {233, 304600}, {0, 130000}, 250,  0x0040 },
-       { {0, 7120}, {466, 609200}, {0, 130000}, 125,  0x0000 }
+       { {0, 3571},  {234,  25485},  {0, 130000}, 1000, 0x08C0 },
+       { {0, 7140},  {467,  919900}, {0, 130000}, 500,  0x0880 },
+       { {0, 14280}, {935,  839800}, {0, 130000}, 250,  0x0840 },
+       { {0, 28570}, {1872, 334950}, {0, 130000}, 125,  0x0800 }
 };
 
 static struct nvs_light_dynamic cm32181_nld_tbl[] = {
@@ -115,7 +115,7 @@ static struct cm_psm cm_psm_tbl[] = {
 struct cm_state {
        struct i2c_client *i2c;
        struct nvs_fn_if *nvs;
-       void *nvs_data;
+       void *nvs_st;
        struct sensor_cfg cfg;
        struct delayed_work dw;
        struct regulator_bulk_data vreg[ARRAY_SIZE(cm_vregs)];
@@ -124,7 +124,6 @@ struct cm_state {
        unsigned int sts;               /* debug flags */
        unsigned int errs;              /* error count */
        unsigned int enabled;           /* enable status */
-       bool iio_ts_en;                 /* use IIO timestamps */
        bool hw_change;                 /* HW changed so drop first sample */
        u16 i2c_addr;                   /* I2C address */
        u8 dev_id;                      /* device ID */
@@ -134,13 +133,10 @@ struct cm_state {
 };
 
 
-static s64 cm_get_time_ns(struct cm_state *st)
+static s64 cm_get_time_ns(void)
 {
        struct timespec ts;
 
-       if (st->iio_ts_en)
-               return iio_get_time_ns();
-
        ktime_get_ts(&ts);
        return timespec_to_ns(&ts);
 }
@@ -296,7 +292,7 @@ static int cm_rd(struct cm_state *st)
                return 0;
        }
 
-       ts = cm_get_time_ns(st);
+       ts = cm_get_time_ns();
        if (st->sts & NVS_STS_SPEW_DATA)
                dev_info(&st->i2c->dev,
                         "poll light hw %hu %lld  diff=%d %lldns  index=%u\n",
@@ -331,14 +327,14 @@ static void cm_read(struct cm_state *st)
 {
        int ret;
 
-       st->nvs->nvs_mutex_lock(st->nvs_data);
+       st->nvs->nvs_mutex_lock(st->nvs_st);
        if (st->enabled) {
                ret = cm_rd(st);
                if (ret < RET_HW_UPDATE)
                        schedule_delayed_work(&st->dw,
                                    msecs_to_jiffies(st->light.poll_delay_ms));
        }
-       st->nvs->nvs_mutex_unlock(st->nvs_data);
+       st->nvs->nvs_mutex_unlock(st->nvs_st);
 }
 
 static void cm_work(struct work_struct *ws)
@@ -423,7 +419,9 @@ static int cm_regs(void *client, int snsr_id, char *buf)
        t = sprintf(buf, "registers:\n");
        for (i = 0; i <= CM_REG_ALS_IF; i++) {
                ret = cm_i2c_rd(st, i, &val);
-               if (!ret)
+               if (ret)
+                       t += sprintf(buf + t, "%#2x=ERR: %d\n", i, ret);
+               else
                        t += sprintf(buf + t, "%#2x=%#4x\n", i, val);
        }
        return t;
@@ -442,8 +440,8 @@ static int cm_suspend(struct device *dev)
        int ret = 0;
 
        st->sts |= NVS_STS_SUSPEND;
-       if (st->nvs && st->nvs_data)
-               ret = st->nvs->suspend(st->nvs_data);
+       if (st->nvs && st->nvs_st)
+               ret = st->nvs->suspend(st->nvs_st);
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s\n", __func__);
        return ret;
@@ -455,8 +453,8 @@ static int cm_resume(struct device *dev)
        struct cm_state *st = i2c_get_clientdata(client);
        int ret = 0;
 
-       if (st->nvs && st->nvs_data)
-               ret = st->nvs->resume(st->nvs_data);
+       if (st->nvs && st->nvs_st)
+               ret = st->nvs->resume(st->nvs_st);
        st->sts &= ~NVS_STS_SUSPEND;
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s\n", __func__);
@@ -470,8 +468,8 @@ static void cm_shutdown(struct i2c_client *client)
        struct cm_state *st = i2c_get_clientdata(client);
 
        st->sts |= NVS_STS_SHUTDOWN;
-       if (st->nvs && st->nvs_data)
-               st->nvs->shutdown(st->nvs_data);
+       if (st->nvs && st->nvs_st)
+               st->nvs->shutdown(st->nvs_st);
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s\n", __func__);
 }
@@ -482,8 +480,8 @@ static int cm_remove(struct i2c_client *client)
 
        if (st != NULL) {
                cm_shutdown(client);
-               if (st->nvs && st->nvs_data)
-                       st->nvs->remove(st->nvs_data);
+               if (st->nvs && st->nvs_st)
+                       st->nvs->remove(st->nvs_st);
                if (st->dw.wq)
                        destroy_workqueue(st->dw.wq);
                cm_pm_exit(st);
@@ -606,12 +604,13 @@ static int cm_id_i2c(struct cm_state *st, const char *name)
 
 static struct sensor_cfg cm_cfg_dflt = {
        .name                   = NVS_LIGHT_STRING,
-       .ch_n                   = ARRAY_SIZE(iio_chan_spec_nvs_light),
-       .ch_inf                 = &iio_chan_spec_nvs_light,
+       .ch_n                   = 1,
+       .ch_sz                  = 4,
        .part                   = CM_NAME,
        .vendor                 = CM_VENDOR,
        .version                = CM_LIGHT_VERSION,
        .delay_us_max           = CM_POLL_DLY_MS_MAX * 1000,
+       .flags                  = SENSOR_FLAG_ON_CHANGE_MODE,
        .scale                  = {
                .ival           = CM_LIGHT_SCALE_IVAL,
                .fval           = CM_LIGHT_SCALE_MICRO,
@@ -624,6 +623,7 @@ static int cm_of_dt(struct cm_state *st, struct device_node *dn)
 {
        u16 als_sm;
        u16 als_pers;
+       int ret;
 
        /* default device specific parameters */
        als_sm = CM_ALS_SM_DFLT;
@@ -637,16 +637,18 @@ static int cm_of_dt(struct cm_state *st, struct device_node *dn)
        st->light.nld_tbl = st->nld_tbl;
        /* device tree parameters */
        if (dn) {
-               /* common NVS IIO programmable parameters */
-               st->iio_ts_en = of_property_read_bool(dn, "iio_timestamps");
+               /* common NVS parameters */
+               ret = nvs_of_dt(dn, &st->cfg, NULL);
+               if (ret == -ENODEV)
+                       return -ENODEV;
+
                /* device specific parameters */
                of_property_read_u16(dn, "als_sm", &als_sm);
                of_property_read_u16(dn, "als_pers", &als_pers);
                of_property_read_u16(dn, "als_psm", &st->als_psm);
                of_property_read_u32(dn, "Rset", &st->r_set);
        }
-       /* common NVS parameters */
-       nvs_of_dt(dn, &st->cfg, NULL);
+
        /* this device supports these programmable parameters */
        if (nvs_light_of_dt(&st->light, dn, NULL)) {
                st->light.nld_i_lo = 0;
@@ -675,8 +677,12 @@ static int cm_probe(struct i2c_client *client,
        st->i2c = client;
        ret = cm_of_dt(st, client->dev.of_node);
        if (ret) {
-               dev_err(&client->dev, "%s _of_dt ERR\n", __func__);
-               ret = -ENODEV;
+               if (ret == -ENODEV) {
+                       dev_info(&client->dev, "%s DT disabled\n", __func__);
+               } else {
+                       dev_err(&client->dev, "%s _of_dt ERR\n", __func__);
+                       ret = -ENODEV;
+               }
                goto cm_probe_exit;
        }
 
@@ -698,7 +704,8 @@ static int cm_probe(struct i2c_client *client,
                goto cm_probe_exit;
        }
 
-       ret = st->nvs->probe(&st->nvs_data, st, &client->dev,
+       st->light.handler = st->nvs->handler;
+       ret = st->nvs->probe(&st->nvs_st, st, &client->dev,
                             &cm_fn_dev, &st->cfg);
        if (ret) {
                dev_err(&client->dev, "%s nvs_probe ERR\n", __func__);
@@ -706,8 +713,7 @@ static int cm_probe(struct i2c_client *client,
                goto cm_probe_exit;
        }
 
-       st->light.nvs_data = st->nvs_data;
-       st->light.handler = st->nvs->handler;
+       st->light.nvs_st = st->nvs_st;
        INIT_DELAYED_WORK(&st->dw, cm_work);
        if (client->irq) {
                ret = request_threaded_irq(client->irq, NULL, cm_irq_thread,
index cc741b92b64758f0c52db163e56f98b6b1bc79bf..1ce21f0d154c53bc97b265561536ad5e62c1102c 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+/* Copyright (c) 2014-2015, NVIDIA CORPORATION.  All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -117,18 +117,15 @@ static struct nvs_light_dynamic isl_nld_tbl[] = {
 struct isl_state {
        struct i2c_client *i2c;
        struct nvs_fn_if *nvs;
-       void *nvs_data[ISL_DEV_N];
+       void *nvs_st[ISL_DEV_N];
        struct sensor_cfg cfg[ISL_DEV_N];
        struct delayed_work dw;
        struct regulator_bulk_data vreg[ARRAY_SIZE(isl_vregs)];
        struct nvs_light light;
        struct nvs_proximity prox;
-       unsigned int dev[ISL_DEV_N];
-       unsigned int snsr_n;            /* number of sensors */
        unsigned int sts;               /* status flags */
        unsigned int errs;              /* error count */
        unsigned int enabled;           /* enable status */
-       bool iio_ts_en;                 /* use IIO timestamps */
        bool irq_dis;                   /* interrupt host disable flag */
        u16 i2c_addr;                   /* I2C address */
        u8 dev_id;                      /* device ID */
@@ -138,13 +135,10 @@ struct isl_state {
 };
 
 
-static s64 isl_get_time_ns(struct isl_state *st)
+static s64 isl_get_time_ns(void)
 {
        struct timespec ts;
 
-       if (st->iio_ts_en)
-               return iio_get_time_ns();
-
        ktime_get_ts(&ts);
        return timespec_to_ns(&ts);
 }
@@ -156,6 +150,30 @@ static void isl_err(struct isl_state *st)
                st->errs--;
 }
 
+static void isl_mutex_lock(struct isl_state *st)
+{
+       unsigned int i;
+
+       if (st->nvs) {
+               for (i = 0; i < ISL_DEV_N; i++) {
+                       if (st->nvs_st[i])
+                               st->nvs->nvs_mutex_lock(st->nvs_st[i]);
+               }
+       }
+}
+
+static void isl_mutex_unlock(struct isl_state *st)
+{
+       unsigned int i;
+
+       if (st->nvs) {
+               for (i = 0; i < ISL_DEV_N; i++) {
+                       if (st->nvs_st[i])
+                               st->nvs->nvs_mutex_unlock(st->nvs_st[i]);
+               }
+       }
+}
+
 static int isl_i2c_read(struct isl_state *st, u8 reg, u16 len, u8 *val)
 {
        struct i2c_msg msg[2];
@@ -438,7 +456,7 @@ static int isl_rd(struct isl_state *st)
        s64 ts;
        int ret = 0;
 
-       ts = isl_get_time_ns(st);
+       ts = isl_get_time_ns();
        if (st->enabled & (1 << ISL_DEV_PROX))
                ret |= isl_rd_prox(st, ts);
        if (st->enabled & (1 << ISL_DEV_LIGHT))
@@ -466,19 +484,16 @@ static unsigned int isl_polldelay(struct isl_state *st)
 
 static void isl_read(struct isl_state *st)
 {
-       unsigned int i;
        int ret;
 
-       for (i = 0; i < st->snsr_n; i++)
-               st->nvs->nvs_mutex_lock(st->nvs_data[i]);
+       isl_mutex_lock(st);
        if (st->enabled) {
                ret = isl_rd(st);
                if (ret < 1)
                        schedule_delayed_work(&st->dw,
                                          msecs_to_jiffies(isl_polldelay(st)));
        }
-       for (i = 0; i < st->snsr_n; i++)
-               st->nvs->nvs_mutex_unlock(st->nvs_data[i]);
+       isl_mutex_unlock(st);
 }
 
 static void isl_work(struct work_struct *ws)
@@ -596,9 +611,11 @@ static int isl_suspend(struct device *dev)
        int ret = 0;
 
        st->sts |= NVS_STS_SUSPEND;
-       for (i = 0; i < st->snsr_n; i++) {
-               if (st->nvs && st->nvs_data[i])
-                       ret |= st->nvs->suspend(st->nvs_data[i]);
+       if (st->nvs) {
+               for (i = 0; i < ISL_DEV_N; i++) {
+                       if (st->nvs_st[i])
+                               ret |= st->nvs->suspend(st->nvs_st[i]);
+               }
        }
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s\n", __func__);
@@ -612,9 +629,11 @@ static int isl_resume(struct device *dev)
        unsigned int i;
        int ret = 0;
 
-       for (i = 0; i < st->snsr_n; i++) {
-               if (st->nvs && st->nvs_data[i])
-                       ret |= st->nvs->resume(st->nvs_data[i]);
+       if (st->nvs) {
+               for (i = 0; i < ISL_DEV_N; i++) {
+                       if (st->nvs_st[i])
+                               ret |= st->nvs->resume(st->nvs_st[i]);
+               }
        }
        st->sts &= ~NVS_STS_SUSPEND;
        if (st->sts & NVS_STS_SPEW_MSG)
@@ -630,9 +649,11 @@ static void isl_shutdown(struct i2c_client *client)
        unsigned int i;
 
        st->sts |= NVS_STS_SHUTDOWN;
-       for (i = 0; i < st->snsr_n; i++) {
-               if (st->nvs && st->nvs_data[i])
-                       st->nvs->shutdown(st->nvs_data[i]);
+       if (st->nvs) {
+               for (i = 0; i < ISL_DEV_N; i++) {
+                       if (st->nvs_st[i])
+                               st->nvs->shutdown(st->nvs_st[i]);
+               }
        }
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s\n", __func__);
@@ -646,9 +667,9 @@ static int isl_remove(struct i2c_client *client)
        if (st != NULL) {
                isl_shutdown(client);
                if (st->nvs) {
-                       for (i = 0; i < st->snsr_n; i++) {
-                               if (st->nvs_data[i])
-                                       st->nvs->remove(st->nvs_data[i]);
+                       for (i = 0; i < ISL_DEV_N; i++) {
+                               if (st->nvs_st[i])
+                                       st->nvs->remove(st->nvs_st[i]);
                        }
                }
                if (st->dw.wq)
@@ -733,8 +754,8 @@ struct sensor_cfg isl_cfg_dflt[] = {
        {
                .name                   = NVS_LIGHT_STRING,
                .snsr_id                = ISL_DEV_LIGHT,
-               .ch_n                   = ARRAY_SIZE(iio_chan_spec_nvs_light),
-               .ch_inf                 = &iio_chan_spec_nvs_light,
+               .ch_n                   = 1,
+               .ch_sz                  = 4,
                .part                   = ISL_NAME,
                .vendor                 = ISL_VENDOR,
                .version                = ISL_LIGHT_VERSION,
@@ -752,6 +773,7 @@ struct sensor_cfg isl_cfg_dflt[] = {
                },
                .delay_us_min           = ISL_POLL_DLY_MS_MIN * 1000,
                .delay_us_max           = ISL_POLL_DLY_MS_MAX * 1000,
+               .flags                  = SENSOR_FLAG_ON_CHANGE_MODE,
                .scale                  = {
                        .ival           = ISL_LIGHT_SCALE_IVAL,
                        .fval           = ISL_LIGHT_SCALE_MICRO,
@@ -762,8 +784,8 @@ struct sensor_cfg isl_cfg_dflt[] = {
        {
                .name                   = NVS_PROXIMITY_STRING,
                .snsr_id                = ISL_DEV_PROX,
-               .ch_n                = ARRAY_SIZE(iio_chan_spec_nvs_proximity),
-               .ch_inf                 = &iio_chan_spec_nvs_proximity,
+               .ch_n                   = 1,
+               .ch_sz                  = 4,
                .part                   = ISL_NAME,
                .vendor                 = ISL_VENDOR,
                .version                = ISL_PROX_VERSION,
@@ -781,6 +803,8 @@ struct sensor_cfg isl_cfg_dflt[] = {
                },
                .delay_us_min           = ISL_POLL_DLY_MS_MIN * 1000,
                .delay_us_max           = ISL_POLL_DLY_MS_MAX * 1000,
+               .flags                  = SENSOR_FLAG_ON_CHANGE_MODE |
+                                         SENSOR_FLAG_WAKE_UP,
                .scale                  = {
                        .ival           = ISL_PROX_SCALE_IVAL,
                        .fval           = ISL_PROX_SCALE_MICRO,
@@ -793,27 +817,32 @@ struct sensor_cfg isl_cfg_dflt[] = {
 static int isl_of_dt(struct isl_state *st, struct device_node *dn)
 {
        unsigned int i;
+       int ret;
 
        for (i = 0; i < ISL_DEV_N; i++)
-               memcpy(&st->cfg[i], &isl_cfg_dflt[i],
-                      sizeof(struct sensor_cfg));
+               memcpy(&st->cfg[i], &isl_cfg_dflt[i], sizeof(st->cfg[0]));
+       st->light.cfg = &st->cfg[ISL_DEV_LIGHT];
        st->light.hw_mask = 0x0FFF;
        st->light.nld_tbl = isl_nld_tbl;
+       st->prox.cfg = &st->cfg[ISL_DEV_PROX];
        st->prox.hw_mask = 0x00FF;
        /* default device specific parameters */
        st->reg_cfg = ISL_CFG_DFLT;
        st->reg_int = ISL_INT_DFLT;
        /* device tree parameters */
        if (dn) {
-               /* common NVS programmable parameters */
-               st->iio_ts_en = of_property_read_bool(dn, "iio_timestamps");
+               /* common NVS parameters */
+               for (i = 0; i < ISL_DEV_N; i++) {
+                       ret = nvs_of_dt(dn, &st->cfg[i], NULL);
+                       if (ret == -ENODEV)
+                               /* the entire device has been disabled */
+                               return -ENODEV;
+               }
+
                /* device specific parameters */
                of_property_read_u8(dn, "configure_reg", &st->reg_cfg);
                of_property_read_u8(dn, "interrupt_reg", &st->reg_int);
        }
-       /* common NVS parameters */
-       for (i = 0; i < ISL_DEV_N; i++)
-               nvs_of_dt(dn, &st->cfg[i], NULL);
        /* this device supports these programmable parameters */
        if (nvs_light_of_dt(&st->light, dn, NULL)) {
                st->light.nld_i_lo = 0;
@@ -851,8 +880,12 @@ static int isl_probe(struct i2c_client *client, const struct i2c_device_id *id)
        st->i2c = client;
        ret = isl_of_dt(st, client->dev.of_node);
        if (ret) {
-               dev_err(&client->dev, "%s _of_dt ERR\n", __func__);
-               ret = -ENODEV;
+               if (ret == -ENODEV) {
+                       dev_info(&client->dev, "%s DT disabled\n", __func__);
+               } else {
+                       dev_err(&client->dev, "%s _of_dt ERR\n", __func__);
+                       ret = -ENODEV;
+               }
                goto isl_probe_exit;
        }
 
@@ -873,23 +906,14 @@ static int isl_probe(struct i2c_client *client, const struct i2c_device_id *id)
                goto isl_probe_exit;
        }
 
+       st->light.handler = st->nvs->handler;
+       st->prox.handler = st->nvs->handler;
        n = 0;
        for (i = 0; i < ISL_DEV_N; i++) {
-               ret = st->nvs->probe(&st->nvs_data[n], st, &client->dev,
+               ret = st->nvs->probe(&st->nvs_st[i], st, &client->dev,
                                     &isl_fn_dev, &st->cfg[i]);
-               if (!ret) {
-                       st->dev[n] = st->cfg[i].snsr_id;
-                       if (st->dev[n] == ISL_DEV_LIGHT) {
-                               st->light.cfg = &st->cfg[i];
-                               st->light.nvs_data = st->nvs_data[n];
-                               st->light.handler = st->nvs->handler;
-                       } else if (st->dev[n] == ISL_DEV_PROX) {
-                               st->prox.cfg = &st->cfg[i];
-                               st->prox.nvs_data = st->nvs_data[n];
-                               st->prox.handler = st->nvs->handler;
-                       }
+               if (!ret)
                        n++;
-               }
        }
        if (!n) {
                dev_err(&client->dev, "%s nvs_probe ERR\n", __func__);
@@ -897,11 +921,17 @@ static int isl_probe(struct i2c_client *client, const struct i2c_device_id *id)
                goto isl_probe_exit;
        }
 
-       st->snsr_n = n;
+       st->light.nvs_st = st->nvs_st[ISL_DEV_LIGHT];
+       st->prox.nvs_st = st->nvs_st[ISL_DEV_PROX];
        INIT_DELAYED_WORK(&st->dw, isl_work);
        if (client->irq) {
                irqflags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
-               irqflags |= IRQF_NO_SUSPEND; /* for proximity */
+               for (i = 0; i < ISL_DEV_N; i++) {
+                       if (st->cfg[i].snsr_id >= 0) {
+                               if (st->cfg[i].flags & SENSOR_FLAG_WAKE_UP)
+                                       irqflags |= IRQF_NO_SUSPEND;
+                       }
+               }
                ret = request_threaded_irq(client->irq, NULL, isl_irq_thread,
                                           irqflags, ISL_NAME, st);
                if (ret) {
index 7112b84385ff137e37fe932cd1e1abbbc7bd544c..86715afada998854ccb0b744f02fa37aedbaf64c 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+/* Copyright (c) 2014-2015, NVIDIA CORPORATION.  All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -72,7 +72,7 @@ static struct nvs_light_dynamic jsa_nld_tbl[] = {
 struct jsa_state {
        struct i2c_client *i2c;
        struct nvs_fn_if *nvs;
-       void *nvs_data;
+       void *nvs_st;
        struct sensor_cfg cfg;
        struct delayed_work dw;
        struct regulator_bulk_data vreg[ARRAY_SIZE(jsa_vregs)];
@@ -283,7 +283,7 @@ static void jsa_read(struct jsa_state *st)
        unsigned int ms;
        int ret;
 
-       st->nvs->nvs_mutex_lock(st->nvs_data);
+       st->nvs->nvs_mutex_lock(st->nvs_st);
        if (st->enabled) {
                if (st->hw_it) {
                        jsa_rd(st);
@@ -309,7 +309,7 @@ static void jsa_read(struct jsa_state *st)
                                 "%s schedule_delayed_work=%ums\n",
                                 __func__, ms);
        }
-       st->nvs->nvs_mutex_unlock(st->nvs_data);
+       st->nvs->nvs_mutex_unlock(st->nvs_st);
 }
 
 static void jsa_work(struct work_struct *ws)
@@ -433,8 +433,8 @@ static int jsa_suspend(struct device *dev)
        int ret = 0;
 
        st->sts |= NVS_STS_SUSPEND;
-       if (st->nvs && st->nvs_data)
-               ret = st->nvs->suspend(st->nvs_data);
+       if (st->nvs && st->nvs_st)
+               ret = st->nvs->suspend(st->nvs_st);
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s\n", __func__);
        return ret;
@@ -446,8 +446,8 @@ static int jsa_resume(struct device *dev)
        struct jsa_state *st = i2c_get_clientdata(client);
        int ret = 0;
 
-       if (st->nvs && st->nvs_data)
-               ret = st->nvs->resume(st->nvs_data);
+       if (st->nvs && st->nvs_st)
+               ret = st->nvs->resume(st->nvs_st);
        st->sts &= ~NVS_STS_SUSPEND;
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s\n", __func__);
@@ -461,8 +461,8 @@ static void jsa_shutdown(struct i2c_client *client)
        struct jsa_state *st = i2c_get_clientdata(client);
 
        st->sts |= NVS_STS_SHUTDOWN;
-       if (st->nvs && st->nvs_data)
-               st->nvs->shutdown(st->nvs_data);
+       if (st->nvs && st->nvs_st)
+               st->nvs->shutdown(st->nvs_st);
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s\n", __func__);
 }
@@ -473,8 +473,8 @@ static int jsa_remove(struct i2c_client *client)
 
        if (st != NULL) {
                jsa_shutdown(client);
-               if (st->nvs && st->nvs_data)
-                       st->nvs->remove(st->nvs_data);
+               if (st->nvs && st->nvs_st)
+                       st->nvs->remove(st->nvs_st);
                if (st->dw.wq)
                        destroy_workqueue(st->dw.wq);
                jsa_pm_exit(st);
@@ -526,8 +526,8 @@ static int jsa_id_i2c(struct jsa_state *st, const char *name)
 
 static struct sensor_cfg jsa_cfg_dflt = {
        .name                   = NVS_LIGHT_STRING,
-       .ch_n                   = ARRAY_SIZE(iio_chan_spec_nvs_light),
-       .ch_inf                 = &iio_chan_spec_nvs_light,
+       .ch_n                   = 1,
+       .ch_sz                  = 4,
        .part                   = JSA_NAME,
        .vendor                 = JSA_VENDOR,
        .version                = JSA_LIGHT_VERSION,
@@ -536,6 +536,7 @@ static struct sensor_cfg jsa_cfg_dflt = {
                .fval           = JSA_LIGHT_MILLIAMP_FVAL,
        },
        .delay_us_max           = JSA_POLL_DLY_MS_MAX * 1000,
+       .flags                  = SENSOR_FLAG_ON_CHANGE_MODE,
        .scale                  = {
                .ival           = JSA_LIGHT_SCALE_IVAL,
                .fval           = JSA_LIGHT_SCALE_MICRO,
@@ -555,7 +556,10 @@ static int jsa_of_dt(struct jsa_state *st, struct device_node *dn)
        st->light.nld_tbl = jsa_nld_tbl;
        /* device tree parameters */
        /* common NVS parameters */
-       nvs_of_dt(dn, &st->cfg, NULL);
+       ret = nvs_of_dt(dn, &st->cfg, NULL);
+       if (ret == -ENODEV)
+               return -ENODEV;
+
        /* this device supports these programmable parameters */
        ret = nvs_light_of_dt(&st->light, dn, NULL);
        if (ret) {
@@ -662,8 +666,12 @@ static int jsa_probe(struct i2c_client *client,
        st->i2c = client;
        ret = jsa_of_dt(st, client->dev.of_node);
        if (ret) {
-               dev_err(&client->dev, "%s _of_dt ERR\n", __func__);
-               ret = -ENODEV;
+               if (ret == -ENODEV) {
+                       dev_info(&client->dev, "%s DT disabled\n", __func__);
+               } else {
+                       dev_err(&client->dev, "%s _of_dt ERR\n", __func__);
+                       ret = -ENODEV;
+               }
                goto jsa_probe_exit;
        }
 
@@ -684,7 +692,8 @@ static int jsa_probe(struct i2c_client *client,
                goto jsa_probe_exit;
        }
 
-       ret = st->nvs->probe(&st->nvs_data, st, &client->dev,
+       st->light.handler = st->nvs->handler;
+       ret = st->nvs->probe(&st->nvs_st, st, &client->dev,
                             &jsa_fn_dev, &st->cfg);
        if (ret) {
                dev_err(&client->dev, "%s nvs_probe ERR\n", __func__);
@@ -692,8 +701,7 @@ static int jsa_probe(struct i2c_client *client,
                goto jsa_probe_exit;
        }
 
-       st->light.nvs_data = st->nvs_data;
-       st->light.handler = st->nvs->handler;
+       st->light.nvs_st = st->nvs_st;
        INIT_DELAYED_WORK(&st->dw, jsa_work);
        dev_info(&client->dev, "%s done\n", __func__);
        return 0;
index 4ea8a204e15e6274162b214e863912a6e62a0b9c..215955f39ddf91d9470f372a5255cb5fc96fb5dc 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+/* Copyright (c) 2014-2015, NVIDIA CORPORATION.  All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -151,18 +151,15 @@ static struct nvs_light_dynamic ltr_nld_tbl[] = {
 struct ltr_state {
        struct i2c_client *i2c;
        struct nvs_fn_if *nvs;
-       void *nvs_data[LTR_DEV_N];
+       void *nvs_st[LTR_DEV_N];
        struct sensor_cfg cfg[LTR_DEV_N];
        struct delayed_work dw;
        struct regulator_bulk_data vreg[ARRAY_SIZE(ltr_vregs)];
        struct nvs_light light;
        struct nvs_proximity prox;
-       unsigned int dev[LTR_DEV_N];
-       unsigned int snsr_n;            /* number of sensors */
        unsigned int sts;               /* status flags */
        unsigned int errs;              /* error count */
        unsigned int enabled;           /* enable status */
-       bool iio_ts_en;                 /* use IIO timestamps */
        u16 i2c_addr;                   /* I2C address */
        u8 dev_id;                      /* device ID */
        u8 ps_contr;                    /* PS_CONTR register default */
@@ -177,13 +174,10 @@ struct ltr_state {
        u8 rc_interrupt;                /* cache of INTERRUPT */
 };
 
-static s64 ltr_get_time_ns(struct ltr_state *st)
+static s64 ltr_get_time_ns(void)
 {
        struct timespec ts;
 
-       if (st->iio_ts_en)
-               return iio_get_time_ns();
-
        ktime_get_ts(&ts);
        return timespec_to_ns(&ts);
 }
@@ -195,6 +189,30 @@ static void ltr_err(struct ltr_state *st)
                st->errs--;
 }
 
+static void ltr_mutex_lock(struct ltr_state *st)
+{
+       unsigned int i;
+
+       if (st->nvs) {
+               for (i = 0; i < LTR_DEV_N; i++) {
+                       if (st->nvs_st[i])
+                               st->nvs->nvs_mutex_lock(st->nvs_st[i]);
+               }
+       }
+}
+
+static void ltr_mutex_unlock(struct ltr_state *st)
+{
+       unsigned int i;
+
+       if (st->nvs) {
+               for (i = 0; i < LTR_DEV_N; i++) {
+                       if (st->nvs_st[i])
+                               st->nvs->nvs_mutex_unlock(st->nvs_st[i]);
+               }
+       }
+}
+
 static int ltr_i2c_read(struct ltr_state *st, u8 reg, u16 len, u8 *val)
 {
        struct i2c_msg msg[2];
@@ -528,7 +546,7 @@ static int ltr_rd(struct ltr_state *st)
                return ret;
 
        if (sts & LTR_REG_STATUS_DATA_MASK) {
-               ts = ltr_get_time_ns(st);
+               ts = ltr_get_time_ns();
                if (st->enabled & (1 << LTR_DEV_PROX))
                        ret |= ltr_rd_prox(st, ts);
                if (st->enabled & (1 << LTR_DEV_LIGHT))
@@ -559,19 +577,16 @@ static unsigned int ltr_polldelay(struct ltr_state *st)
 
 static void ltr_read(struct ltr_state *st)
 {
-       unsigned int i;
        int ret;
 
-       for (i = 0; i < st->snsr_n; i++)
-               st->nvs->nvs_mutex_lock(st->nvs_data[i]);
+       ltr_mutex_lock(st);
        if (st->enabled) {
                ret = ltr_rd(st);
                if (ret < 1)
                        schedule_delayed_work(&st->dw,
                                          msecs_to_jiffies(ltr_polldelay(st)));
        }
-       for (i = 0; i < st->snsr_n; i++)
-               st->nvs->nvs_mutex_unlock(st->nvs_data[i]);
+       ltr_mutex_unlock(st);
 }
 
 static void ltr_work(struct work_struct *ws)
@@ -763,9 +778,11 @@ static int ltr_suspend(struct device *dev)
        int ret = 0;
 
        st->sts |= NVS_STS_SUSPEND;
-       for (i = 0; i < st->snsr_n; i++) {
-               if (st->nvs && st->nvs_data[i])
-                       ret |= st->nvs->suspend(st->nvs_data[i]);
+       if (st->nvs) {
+               for (i = 0; i < LTR_DEV_N; i++) {
+                       if (st->nvs_st[i])
+                               ret |= st->nvs->suspend(st->nvs_st[i]);
+               }
        }
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s\n", __func__);
@@ -779,9 +796,11 @@ static int ltr_resume(struct device *dev)
        unsigned int i;
        int ret = 0;
 
-       for (i = 0; i < st->snsr_n; i++) {
-               if (st->nvs && st->nvs_data[i])
-                       ret |= st->nvs->resume(st->nvs_data[i]);
+       if (st->nvs) {
+               for (i = 0; i < LTR_DEV_N; i++) {
+                       if (st->nvs_st[i])
+                               ret |= st->nvs->resume(st->nvs_st[i]);
+               }
        }
        st->sts &= ~NVS_STS_SUSPEND;
        if (st->sts & NVS_STS_SPEW_MSG)
@@ -797,9 +816,11 @@ static void ltr_shutdown(struct i2c_client *client)
        unsigned int i;
 
        st->sts |= NVS_STS_SHUTDOWN;
-       for (i = 0; i < st->snsr_n; i++) {
-               if (st->nvs && st->nvs_data[i])
-                       st->nvs->shutdown(st->nvs_data[i]);
+       if (st->nvs) {
+               for (i = 0; i < LTR_DEV_N; i++) {
+                       if (st->nvs_st[i])
+                               st->nvs->shutdown(st->nvs_st[i]);
+               }
        }
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s\n", __func__);
@@ -813,9 +834,9 @@ static int ltr_remove(struct i2c_client *client)
        if (st != NULL) {
                ltr_shutdown(client);
                if (st->nvs) {
-                       for (i = 0; i < st->snsr_n; i++) {
-                               if (st->nvs_data[i])
-                                       st->nvs->remove(st->nvs_data[i]);
+                       for (i = 0; i < LTR_DEV_N; i++) {
+                               if (st->nvs_st[i])
+                                       st->nvs->remove(st->nvs_st[i]);
                        }
                }
                if (st->dw.wq)
@@ -922,8 +943,8 @@ struct sensor_cfg ltr_cfg_dflt[] = {
        {
                .name                   = NVS_LIGHT_STRING,
                .snsr_id                = LTR_DEV_LIGHT,
-               .ch_n                   = ARRAY_SIZE(iio_chan_spec_nvs_light),
-               .ch_inf                 = &iio_chan_spec_nvs_light,
+               .ch_n                   = 1,
+               .ch_sz                  = 4,
                .part                   = LTR_NAME,
                .vendor                 = LTR_VENDOR,
                .version                = LTR_LIGHT_VERSION,
@@ -941,6 +962,7 @@ struct sensor_cfg ltr_cfg_dflt[] = {
                },
                .delay_us_min           = LTR_POLL_DLY_MS_MIN * 1000,
                .delay_us_max           = LTR_POLL_DLY_MS_MAX * 1000,
+               .flags                  = SENSOR_FLAG_ON_CHANGE_MODE,
                .scale                  = {
                        .ival           = LTR_LIGHT_SCALE_IVAL,
                        .fval           = LTR_LIGHT_SCALE_MICRO,
@@ -951,8 +973,8 @@ struct sensor_cfg ltr_cfg_dflt[] = {
        {
                .name                   = NVS_PROXIMITY_STRING,
                .snsr_id                = LTR_DEV_PROX,
-               .ch_n                = ARRAY_SIZE(iio_chan_spec_nvs_proximity),
-               .ch_inf                 = &iio_chan_spec_nvs_proximity,
+               .ch_n                   = 1,
+               .ch_sz                  = 4,
                .part                   = LTR_NAME,
                .vendor                 = LTR_VENDOR,
                .version                = LTR_PROX_VERSION,
@@ -970,6 +992,8 @@ struct sensor_cfg ltr_cfg_dflt[] = {
                },
                .delay_us_min           = LTR_POLL_DLY_MS_MIN * 1000,
                .delay_us_max           = LTR_POLL_DLY_MS_MAX * 1000,
+               .flags                  = SENSOR_FLAG_ON_CHANGE_MODE |
+                                         SENSOR_FLAG_WAKE_UP,
                .scale                  = {
                        .ival           = LTR_PROX_SCALE_IVAL,
                        .fval           = LTR_PROX_SCALE_MICRO,
@@ -982,10 +1006,15 @@ struct sensor_cfg ltr_cfg_dflt[] = {
 static int ltr_of_dt(struct ltr_state *st, struct device_node *dn)
 {
        unsigned int i;
+       int ret;
 
        for (i = 0; i < LTR_DEV_N; i++)
-               memcpy(&st->cfg[i], &ltr_cfg_dflt[i],
-                      sizeof(struct sensor_cfg));
+               memcpy(&st->cfg[i], &ltr_cfg_dflt[i], sizeof(st->cfg[0]));
+       st->light.cfg = &st->cfg[LTR_DEV_LIGHT];
+       st->light.hw_mask = 0xFFFF;
+       st->light.nld_tbl = ltr_nld_tbl;
+       st->prox.cfg = &st->cfg[LTR_DEV_PROX];
+       st->prox.hw_mask = 0xFFFF;
        /* default device specific parameters */
        st->ps_contr = LTR_REG_PS_CONTR_DFLT;
        st->ps_led = LTR_REG_PS_LED_DFLT;
@@ -995,8 +1024,14 @@ static int ltr_of_dt(struct ltr_state *st, struct device_node *dn)
        st->interrupt_persist = LTR_REG_INTERRUPT_PERSIST_DFLT;
        /* device tree parameters */
        if (dn) {
-               /* common NVS programmable parameters */
-               st->iio_ts_en = of_property_read_bool(dn, "iio_timestamps");
+               /* common NVS parameters */
+               for (i = 0; i < LTR_DEV_N; i++) {
+                       ret = nvs_of_dt(dn, &st->cfg[i], NULL);
+                       if (ret == -ENODEV)
+                               /* the entire device has been disabled */
+                               return -ENODEV;
+               }
+
                /* device specific parameters */
                of_property_read_u8(dn, "register_ps_contr", &st->ps_contr);
                st->ps_contr &= LTR_REG_PS_CONTR_POR_MASK;
@@ -1013,9 +1048,6 @@ static int ltr_of_dt(struct ltr_state *st, struct device_node *dn)
                of_property_read_u8(dn, "register_interrupt_persist",
                                    &st->interrupt_persist);
        }
-       /* common NVS parameters */
-       for (i = 0; i < LTR_DEV_N; i++)
-               nvs_of_dt(dn, &st->cfg[i], NULL);
        /* this device supports these programmable parameters */
        if (nvs_light_of_dt(&st->light, dn, NULL)) {
                st->light.nld_i_lo = 0;
@@ -1043,8 +1075,12 @@ static int ltr_probe(struct i2c_client *client, const struct i2c_device_id *id)
        st->i2c = client;
        ret = ltr_of_dt(st, client->dev.of_node);
        if (ret) {
-               dev_err(&client->dev, "%s _of_dt ERR\n", __func__);
-               ret = -ENODEV;
+               if (ret == -ENODEV) {
+                       dev_info(&client->dev, "%s DT disabled\n", __func__);
+               } else {
+                       dev_err(&client->dev, "%s _of_dt ERR\n", __func__);
+                       ret = -ENODEV;
+               }
                goto ltr_probe_exit;
        }
 
@@ -1065,31 +1101,14 @@ static int ltr_probe(struct i2c_client *client, const struct i2c_device_id *id)
                goto ltr_probe_exit;
        }
 
+       st->light.handler = st->nvs->handler;
+       st->prox.handler = st->nvs->handler;
        n = 0;
        for (i = 0; i < LTR_DEV_N; i++) {
-               if (st->dev_id == LTR_DEVID_659PS) {
-                       if (st->cfg[i].snsr_id == LTR_DEV_LIGHT)
-                               continue;
-               }
-
-               ret = st->nvs->probe(&st->nvs_data[n], st, &client->dev,
+               ret = st->nvs->probe(&st->nvs_st[i], st, &client->dev,
                                     &ltr_fn_dev, &st->cfg[i]);
-               if (!ret) {
-                       st->dev[n] = st->cfg[i].snsr_id;
-                       if (st->dev[n] == LTR_DEV_LIGHT) {
-                               st->light.cfg = &st->cfg[i];
-                               st->light.nvs_data = st->nvs_data[n];
-                               st->light.handler = st->nvs->handler;
-                               st->light.hw_mask = 0xFFFF;
-                               st->light.nld_tbl = ltr_nld_tbl;
-                       } else if (st->dev[n] == LTR_DEV_PROX) {
-                               st->prox.cfg = &st->cfg[i];
-                               st->prox.nvs_data = st->nvs_data[n];
-                               st->prox.handler = st->nvs->handler;
-                               st->prox.hw_mask = 0xFFFF;
-                       }
+               if (!ret)
                        n++;
-               }
        }
        if (!n) {
                dev_err(&client->dev, "%s nvs_probe ERR\n", __func__);
@@ -1097,15 +1116,21 @@ static int ltr_probe(struct i2c_client *client, const struct i2c_device_id *id)
                goto ltr_probe_exit;
        }
 
-       st->snsr_n = n;
+       st->light.nvs_st = st->nvs_st[LTR_DEV_LIGHT];
+       st->prox.nvs_st = st->nvs_st[LTR_DEV_PROX];
        INIT_DELAYED_WORK(&st->dw, ltr_work);
        if (client->irq) {
-               /* IRQF_NO_SUSPEND for proximity */
-               irqflags = IRQF_NO_SUSPEND | IRQF_ONESHOT;
+               irqflags = IRQF_ONESHOT;
                if (st->interrupt & LTR_REG_INTERRUPT_POLARITY)
                        irqflags |= IRQF_TRIGGER_RISING;
                else
                        irqflags |= IRQF_TRIGGER_FALLING;
+               for (i = 0; i < LTR_DEV_N; i++) {
+                       if (st->cfg[i].snsr_id >= 0) {
+                               if (st->cfg[i].flags & SENSOR_FLAG_WAKE_UP)
+                                       irqflags |= IRQF_NO_SUSPEND;
+                       }
+               }
                ret = request_threaded_irq(client->irq, NULL, ltr_irq_thread,
                                           irqflags, LTR_NAME, st);
                if (ret) {
index 5d0d44e0609e72f98268600b38fdbfbabedcd784..04be3c3fec46cb339fc9a46e11f7f2227863a54b 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+/* Copyright (c) 2014-2015, NVIDIA CORPORATION.  All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -189,18 +189,15 @@ static unsigned int mx_ambtim_mask[] = {
 struct mx_state {
        struct i2c_client *i2c;
        struct nvs_fn_if *nvs;
-       void *nvs_data[MX_DEV_N];
+       void *nvs_st[MX_DEV_N];
        struct sensor_cfg cfg[MX_DEV_N];
        struct delayed_work dw;
        struct regulator_bulk_data vreg[ARRAY_SIZE(mx_vregs)];
        struct nvs_light light;
        struct nvs_proximity prox;
-       unsigned int dev[MX_DEV_N];
-       unsigned int snsr_n;            /* number of sensors */
        unsigned int sts;               /* status flags */
        unsigned int errs;              /* error count */
        unsigned int enabled;           /* enable status */
-       bool iio_ts_en;                 /* use IIO timestamps */
        u16 i2c_addr;                   /* I2C address */
        u8 dev_id;                      /* device ID */
        u8 amb_cfg;                     /* ambient configuration register */
@@ -211,13 +208,10 @@ struct mx_state {
 };
 
 
-static s64 mx_get_time_ns(struct mx_state *st)
+static s64 mx_get_time_ns(void)
 {
        struct timespec ts;
 
-       if (st->iio_ts_en)
-               return iio_get_time_ns();
-
        ktime_get_ts(&ts);
        return timespec_to_ns(&ts);
 }
@@ -229,6 +223,30 @@ static void mx_err(struct mx_state *st)
                st->errs--;
 }
 
+static void mx_mutex_lock(struct mx_state *st)
+{
+       unsigned int i;
+
+       if (st->nvs) {
+               for (i = 0; i < MX_DEV_N; i++) {
+                       if (st->nvs_st[i])
+                               st->nvs->nvs_mutex_lock(st->nvs_st[i]);
+               }
+       }
+}
+
+static void mx_mutex_unlock(struct mx_state *st)
+{
+       unsigned int i;
+
+       if (st->nvs) {
+               for (i = 0; i < MX_DEV_N; i++) {
+                       if (st->nvs_st[i])
+                               st->nvs->nvs_mutex_unlock(st->nvs_st[i]);
+               }
+       }
+}
+
 static int mx_i2c_read(struct mx_state *st, u8 reg, u16 len, u8 *val)
 {
        struct i2c_msg msg[2];
@@ -529,7 +547,7 @@ static int mx_rd(struct mx_state *st)
                return RET_POLL_NEXT;
        }
 
-       ts = mx_get_time_ns(st);
+       ts = mx_get_time_ns();
        if (st->enabled & (1 << MX_DEV_PROX))
                ret |= mx_rd_prox(st, ts);
        if (st->enabled & (1 << MX_DEV_LIGHT))
@@ -557,19 +575,16 @@ static unsigned int mx_polldelay(struct mx_state *st)
 
 static void mx_read(struct mx_state *st)
 {
-       unsigned int i;
        int ret;
 
-       for (i = 0; i < st->snsr_n; i++)
-               st->nvs->nvs_mutex_lock(st->nvs_data[i]);
+       mx_mutex_lock(st);
        if (st->enabled) {
                ret = mx_rd(st);
                if (ret < 1)
                        schedule_delayed_work(&st->dw,
                                           msecs_to_jiffies(mx_polldelay(st)));
        }
-       for (i = 0; i < st->snsr_n; i++)
-               st->nvs->nvs_mutex_unlock(st->nvs_data[i]);
+       mx_mutex_unlock(st);
 }
 
 static void mx_work(struct work_struct *ws)
@@ -709,9 +724,11 @@ static int mx_suspend(struct device *dev)
        int ret = 0;
 
        st->sts |= NVS_STS_SUSPEND;
-       for (i = 0; i < st->snsr_n; i++) {
-               if (st->nvs && st->nvs_data[i])
-                       ret |= st->nvs->suspend(st->nvs_data[i]);
+       if (st->nvs) {
+               for (i = 0; i < MX_DEV_N; i++) {
+                       if (st->nvs_st[i])
+                               ret |= st->nvs->suspend(st->nvs_st[i]);
+               }
        }
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s\n", __func__);
@@ -725,9 +742,11 @@ static int mx_resume(struct device *dev)
        unsigned int i;
        int ret = 0;
 
-       for (i = 0; i < st->snsr_n; i++) {
-               if (st->nvs && st->nvs_data[i])
-                       ret |= st->nvs->resume(st->nvs_data[i]);
+       if (st->nvs) {
+               for (i = 0; i < MX_DEV_N; i++) {
+                       if (st->nvs_st[i])
+                               ret |= st->nvs->resume(st->nvs_st[i]);
+               }
        }
        st->sts &= ~NVS_STS_SUSPEND;
        if (st->sts & NVS_STS_SPEW_MSG)
@@ -743,9 +762,11 @@ static void mx_shutdown(struct i2c_client *client)
        unsigned int i;
 
        st->sts |= NVS_STS_SHUTDOWN;
-       for (i = 0; i < st->snsr_n; i++) {
-               if (st->nvs && st->nvs_data[i])
-                       st->nvs->shutdown(st->nvs_data[i]);
+       if (st->nvs) {
+               for (i = 0; i < MX_DEV_N; i++) {
+                       if (st->nvs_st[i])
+                               st->nvs->shutdown(st->nvs_st[i]);
+               }
        }
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s\n", __func__);
@@ -759,9 +780,9 @@ static int mx_remove(struct i2c_client *client)
        if (st != NULL) {
                mx_shutdown(client);
                if (st->nvs) {
-                       for (i = 0; i < st->snsr_n; i++) {
-                               if (st->nvs_data[i])
-                                       st->nvs->remove(st->nvs_data[i]);
+                       for (i = 0; i < MX_DEV_N; i++) {
+                               if (st->nvs_st[i])
+                                       st->nvs->remove(st->nvs_st[i]);
                        }
                }
                if (st->dw.wq)
@@ -861,8 +882,8 @@ struct sensor_cfg mx_cfg_dflt[] = {
        {
                .name                   = NVS_LIGHT_STRING,
                .snsr_id                = MX_DEV_LIGHT,
-               .ch_n                   = ARRAY_SIZE(iio_chan_spec_nvs_light),
-               .ch_inf                 = &iio_chan_spec_nvs_light,
+               .ch_n                   = 1,
+               .ch_sz                  = 4,
                .part                   = MX_NAME,
                .vendor                 = MX_VENDOR,
                .version                = MX_LIGHT_VERSION,
@@ -880,6 +901,7 @@ struct sensor_cfg mx_cfg_dflt[] = {
                },
                .delay_us_min           = MX_POLL_DLY_MS_MIN * 1000,
                .delay_us_max           = MX_POLL_DLY_MS_MAX * 1000,
+               .flags                  = SENSOR_FLAG_ON_CHANGE_MODE,
                .scale                  = {
                        .ival           = MX_LIGHT_SCALE_IVAL,
                        .fval           = MX_LIGHT_SCALE_MICRO,
@@ -889,9 +911,8 @@ struct sensor_cfg mx_cfg_dflt[] = {
        },
        {
                .name                   = NVS_PROXIMITY_STRING,
-               .snsr_id                = MX_DEV_PROX,
-               .ch_n                = ARRAY_SIZE(iio_chan_spec_nvs_proximity),
-               .ch_inf                 = &iio_chan_spec_nvs_proximity,
+               .ch_n                   = 1,
+               .ch_sz                  = 4,
                .part                   = MX_NAME,
                .vendor                 = MX_VENDOR,
                .version                = MX_PROX_VERSION,
@@ -909,6 +930,8 @@ struct sensor_cfg mx_cfg_dflt[] = {
                },
                .delay_us_min           = MX_POLL_DLY_MS_MIN * 1000,
                .delay_us_max           = MX_POLL_DLY_MS_MAX * 1000,
+               .flags                  = SENSOR_FLAG_ON_CHANGE_MODE |
+                                         SENSOR_FLAG_WAKE_UP,
                .scale                  = {
                        .ival           = MX_PROX_SCALE_IVAL,
                        .fval           = MX_PROX_SCALE_MICRO,
@@ -921,25 +944,30 @@ struct sensor_cfg mx_cfg_dflt[] = {
 static int mx_of_dt(struct mx_state *st, struct device_node *dn)
 {
        unsigned int i;
+       int ret;
 
        for (i = 0; i < MX_DEV_N; i++)
-               memcpy(&st->cfg[i], &mx_cfg_dflt[i],
-                      sizeof(struct sensor_cfg));
+               memcpy(&st->cfg[i], &mx_cfg_dflt[i], sizeof(st->cfg[0]));
+       st->light.cfg = &st->cfg[MX_DEV_LIGHT];
+       st->prox.cfg = &st->cfg[MX_DEV_PROX];
        /* default device specific parameters */
        st->amb_cfg = MX_AMB_CFG_DFLT;
        st->prx_cfg = MX_PRX_CFG_DFLT;
        /* device tree parameters */
        if (dn) {
-               /* common NVS programmable parameters */
-               st->iio_ts_en = of_property_read_bool(dn, "iio_timestamps");
+               /* common NVS parameters */
+               for (i = 0; i < MX_DEV_N; i++) {
+                       ret = nvs_of_dt(dn, &st->cfg[i], NULL);
+                       if (ret == -ENODEV)
+                               /* the entire device has been disabled */
+                               return -ENODEV;
+               }
+
                /* device specific parameters */
                of_property_read_u8(dn, "ambient_cfg_reg", &st->amb_cfg);
                of_property_read_u8(dn, "proximity_cfg_reg", &st->prx_cfg);
                of_property_read_u8(dn, "threshold_persist_reg", &st->thr_cfg);
        }
-       /* common NVS parameters */
-       for (i = 0; i < MX_DEV_N; i++)
-               nvs_of_dt(dn, &st->cfg[i], NULL);
        /* this device supports these programmable parameters */
        if (nvs_light_of_dt(&st->light, dn, NULL)) {
                st->light.nld_i_lo = 0;
@@ -967,8 +995,12 @@ static int mx_probe(struct i2c_client *client, const struct i2c_device_id *id)
        st->i2c = client;
        ret = mx_of_dt(st, client->dev.of_node);
        if (ret) {
-               dev_err(&client->dev, "%s _of_dt ERR\n", __func__);
-               ret = -ENODEV;
+               if (ret == -ENODEV) {
+                       dev_info(&client->dev, "%s DT disabled\n", __func__);
+               } else {
+                       dev_err(&client->dev, "%s _of_dt ERR\n", __func__);
+                       ret = -ENODEV;
+               }
                goto mx_probe_exit;
        }
 
@@ -989,28 +1021,21 @@ static int mx_probe(struct i2c_client *client, const struct i2c_device_id *id)
                goto mx_probe_exit;
        }
 
+       st->light.handler = st->nvs->handler;
+       st->prox.handler = st->nvs->handler;
        n = 0;
        for (i = 0; i < MX_DEV_N; i++) {
                if (st->dev_id != MX_DEVID_MAX44005) {
-                       if (st->cfg[i].snsr_id == MX_DEV_PROX)
+                       if (st->cfg[i].snsr_id == MX_DEV_PROX) {
+                               st->cfg[i].snsr_id = -1;
                                continue;
+                       }
                }
 
-               ret = st->nvs->probe(&st->nvs_data[n], st, &client->dev,
+               ret = st->nvs->probe(&st->nvs_st[i], st, &client->dev,
                                     &mx_fn_dev, &st->cfg[i]);
-               if (!ret) {
-                       st->dev[n] = st->cfg[i].snsr_id;
-                       if (st->dev[n] == MX_DEV_LIGHT) {
-                               st->light.cfg = &st->cfg[i];
-                               st->light.nvs_data = st->nvs_data[n];
-                               st->light.handler = st->nvs->handler;
-                       } else if (st->dev[n] == MX_DEV_PROX) {
-                               st->prox.cfg = &st->cfg[i];
-                               st->prox.nvs_data = st->nvs_data[n];
-                               st->prox.handler = st->nvs->handler;
-                       }
+               if (!ret)
                        n++;
-               }
        }
        if (!n) {
                dev_err(&client->dev, "%s nvs_probe ERR\n", __func__);
@@ -1018,12 +1043,17 @@ static int mx_probe(struct i2c_client *client, const struct i2c_device_id *id)
                goto mx_probe_exit;
        }
 
-       st->snsr_n = n;
+       st->light.nvs_st = st->nvs_st[MX_DEV_LIGHT];
+       st->prox.nvs_st = st->nvs_st[MX_DEV_PROX];
        INIT_DELAYED_WORK(&st->dw, mx_work);
        if (client->irq) {
                irqflags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
-               if (st->dev_id == MX_DEVID_MAX44005)
-                       irqflags |= IRQF_NO_SUSPEND; /* for proximity */
+               for (i = 0; i < MX_DEV_N; i++) {
+                       if (st->cfg[i].snsr_id >= 0) {
+                               if (st->cfg[i].flags & SENSOR_FLAG_WAKE_UP)
+                                       irqflags |= IRQF_NO_SUSPEND;
+                       }
+               }
                ret = request_threaded_irq(client->irq, NULL, mx_irq_thread,
                                           irqflags, MX_NAME, st);
                if (ret) {
index 1714e875fc035df73555644079ac3439d862778b..e38b7b02681e207736c5a92ba37b1c4c67e59b5f 100644 (file)
@@ -1460,6 +1460,11 @@ static int akm_of_dt(struct akm_state *st, struct device_node *dn)
 {
        char const *pchar;
        u8 cfg;
+       int ret;
+
+       ret = nvs_of_dt(dn, &st->cfg, NULL);
+       if (ret == -ENODEV)
+               return -ENODEV;
 
        /* this device supports these programmable parameters */
        if (!(of_property_read_string(dn, "nvi_config", &pchar))) {
@@ -1497,8 +1502,17 @@ static int akm_probe(struct i2c_client *client,
        st->cfg.matrix[8] = 1;
        if (client->dev.of_node) {
                ret = akm_of_dt(st, client->dev.of_node);
-               if (ret)
+               if (ret) {
+                       if (ret == -ENODEV) {
+                               dev_info(&client->dev, "%s DT disabled\n",
+                                        __func__);
+                       } else {
+                               dev_err(&client->dev, "%s _of_dt ERR\n",
+                                       __func__);
+                               ret = -ENODEV;
+                       }
                        goto akm_probe_err;
+               }
 #if AKM_NVI_MPU_SUPPORT
        } else {
                pd = (struct mpu_platform_data *)
@@ -1517,9 +1531,6 @@ static int akm_probe(struct i2c_client *client,
 
        akm_init_hw(st);
        akm_pm(st, false);
-       ret = nvs_of_dt(client->dev.of_node, &st->cfg, NULL);
-       if (ret)
-               dev_info(&client->dev, "%s nvs_of_dt ERR\n", __func__);
        akm_fn_dev.errs = &st->errs;
        akm_fn_dev.sts = &st->sts;
        st->nvs = nvs_iio();
index e1131e5ab434d426769eea27c33fd211f741acc1..afed3693f31087ff9f414bba9f0957f12f70fae1 100644 (file)
@@ -1810,13 +1810,23 @@ static int bmp_of_dt(struct bmp_state *st, struct device_node *dn)
 {
        char const *pchar;
        u8 cfg;
+       unsigned int i;
+       int ret;
 
-       /* this device supports these programmable parameters */
-       if (!(of_property_read_string(dn, "nvi_config", &pchar))) {
-               for (cfg = 0; cfg < ARRAY_SIZE(bmp_configs); cfg++) {
-                       if (!strcasecmp(pchar, bmp_configs[cfg])) {
-                               st->nvi_config = cfg;
-                               break;
+       if (dn) {
+               for (i = 0; i < BMP_DEV_N; i++) {
+                       ret = nvs_of_dt(dn, &st->cfg[i], NULL);
+                       if (ret == -ENODEV)
+                               return -ENODEV;
+               }
+
+               /* this device supports these programmable parameters */
+               if (!(of_property_read_string(dn, "nvi_config", &pchar))) {
+                       for (cfg = 0; cfg < ARRAY_SIZE(bmp_configs); cfg++) {
+                               if (!strcasecmp(pchar, bmp_configs[cfg])) {
+                                       st->nvi_config = cfg;
+                                       break;
+                               }
                        }
                }
        }
@@ -1840,10 +1850,15 @@ static int bmp_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, st);
        st->i2c = client;
-       if (client->dev.of_node) {
-               ret = bmp_of_dt(st, client->dev.of_node);
-               if (ret)
-                       goto bmp_probe_err;
+       ret = bmp_of_dt(st, client->dev.of_node);
+       if (ret) {
+               if (ret == -ENODEV) {
+                       dev_info(&client->dev, "%s DT disabled\n", __func__);
+               } else {
+                       dev_err(&client->dev, "%s _of_dt ERR\n", __func__);
+                       ret = -ENODEV;
+               }
+               goto bmp_probe_err;
        }
 
        bmp_pm_init(st);
index 3d9ae044345dd81f0cd396e89c905b803c58d978..d84cbb7cdfce9faf9caaea9ec22d2f401abd246f 100644 (file)
@@ -4,14 +4,14 @@
 menu "Proximity sensors"
 
 config NVS_IQS2X3
-       tristate "Maxim MAX4400X ALS/Proximity"
+       tristate "Azoteq IQS253/IQS263 SAR proximity"
        select NVS_IIO
        select NVS_PROXIMITY
        select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
        depends on I2C
        help
-         Say Y here for Azoteq IQS253 and IQS263 proximity support.
+         Say Y here for Azoteq IQS253 and IQS263 SAR proximity support.
 
          The driver uses the NVS (NVidia Sensor) IIO and proximity
          framework.
index 613b133e41547fef939c3d5f9cada95511f1763a..d594d1dba3fdc60c44c2da0463af5e959f486edf 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/nvs_proximity.h>
 
 
-#define IQS_DRIVER_VERSION             (4)
+#define IQS_DRIVER_VERSION             (6)
 #define IQS_VENDOR                     "Azoteq"
 #define IQS_NAME                       "iqs2x3"
 #define IQS_NAME_IQS253                        "iqs253"
@@ -244,7 +244,8 @@ static const struct iqs_hal const iqs253_hal_tbl[] = {
 };
 
 #define IQS_DT_INIT_N                  (128) /* max DT init bytes */
-#define IQS_DT_EN_N                    (64) /* max DT enable bytes */
+#define IQS_DT_ABLE_N                  (64) /* max DT en/dis-able bytes */
+#define IQS_DT_EVNT_N                  (32) /* max DT en/dis-able bytes */
 #define IQS263_MSG_N                   (14)
 #define IQS253_MSG_N                   (9)
 
@@ -416,10 +417,16 @@ struct iqs_state {
        unsigned char *wr_reseed;
        unsigned char dt_init263[IQS_DT_INIT_N];
        unsigned char dt_init253[IQS_DT_INIT_N];
-       unsigned char dt_en_prx263[IQS_DT_EN_N];
-       unsigned char dt_en_tch263[IQS_DT_EN_N];
-       unsigned char dt_en_prx253[IQS_DT_EN_N];
-       unsigned char dt_en_tch253[IQS_DT_EN_N];
+       unsigned char dt_en_prx263[IQS_DT_ABLE_N];
+       unsigned char dt_en_tch263[IQS_DT_ABLE_N];
+       unsigned char dt_en_prx253[IQS_DT_ABLE_N];
+       unsigned char dt_en_tch253[IQS_DT_ABLE_N];
+       unsigned char dt_dis_prx263[IQS_DT_ABLE_N];
+       unsigned char dt_dis_tch263[IQS_DT_ABLE_N];
+       unsigned char dt_dis_prx253[IQS_DT_ABLE_N];
+       unsigned char dt_dis_tch253[IQS_DT_ABLE_N];
+       unsigned char dt_evnt263[IQS_DT_EVNT_N];
+       unsigned char dt_evnt253[IQS_DT_EVNT_N];
        u8 rc[IQS_BI_N];                /* register cache */
 };
 
@@ -745,7 +752,7 @@ static int iqs_write(struct iqs_state *st, unsigned char *wr)
        int ret;
 
        ret = iqs_wr(st, wr);
-       if (!ret)
+       if (st->msg_n && !ret)
                ret = iqs_i2c(st);
        return ret;
 }
@@ -788,6 +795,19 @@ static void iqs_op_rd(struct iqs_state *st)
        st->op_i = st->op_read_n; /* force new read cycle */
 }
 
+static int iqs_init(struct iqs_state *st)
+{
+       unsigned char *wr = st->dt_init263;
+       int ret = 0;
+
+       if (st->dev_id == IQS_DEVID_IQS253)
+               wr = st->dt_init253;
+       if (st->hal_tbl_n)
+               /* only if HAL initialized */
+               ret = iqs_write(st, wr);
+       return ret;
+}
+
 static int iqs_en(struct iqs_state *st, int snsr_id)
 {
        unsigned char *wr;
@@ -807,32 +827,37 @@ static int iqs_en(struct iqs_state *st, int snsr_id)
                return -EINVAL;
        }
 
+       /* if sensor enabled */
        ret = iqs_write(st, wr);
        if (!ret)
                ret = nvs_proximity_enable(&st->prox[snsr_id]);
        return ret;
 }
 
-static int iqs_init(struct iqs_state *st)
+static int iqs_dis(struct iqs_state *st, int snsr_id)
 {
-       unsigned char *wr = st->dt_init263;
+       unsigned char *wr;
        int ret = 0;
 
-       if (st->dev_id == IQS_DEVID_IQS253)
-               wr = st->dt_init253;
-       if (st->hal_tbl_n)
-               /* only if HAL initialized */
-               ret = iqs_write(st, wr);
-       return ret;
-}
-
-static int iqs_dis(struct iqs_state *st)
-{
-       int ret = 0;
+       if (snsr_id == IQS_DEV_PROX) {
+               if (st->dev_id == IQS_DEVID_IQS253)
+                       wr = st->dt_dis_prx253;
+               else
+                       wr = st->dt_dis_prx263;
+       } else if (snsr_id == IQS_DEV_TOUCH) {
+               if (st->dev_id == IQS_DEVID_IQS253)
+                       wr = st->dt_dis_tch253;
+               else
+                       wr = st->dt_dis_tch263;
+       } else if (snsr_id < 0) {
+               wr = st->wr_disable;
+       } else {
+               return -EINVAL;
+       }
 
        if (st->hal_tbl_n)
                /* only if HAL initialized */
-               ret = iqs_write(st, st->wr_disable);
+               ret = iqs_write(st, wr);
        return ret;
 }
 
@@ -849,13 +874,13 @@ static int iqs_pm(struct iqs_state *st, bool enable)
        } else {
                ret = nvs_vregs_sts(st->vreg, ARRAY_SIZE(iqs_vregs));
                if ((ret < 0) || (ret == ARRAY_SIZE(iqs_vregs))) {
-                       ret = iqs_dis(st);
+                       ret = iqs_dis(st, -1);
                } else if (ret > 0) {
                        nvs_vregs_enable(&st->i2c->dev, st->vreg,
                                         ARRAY_SIZE(iqs_vregs));
                        mdelay(IQS_HW_DELAY_MS);
                        ret = iqs_init(st);
-                       ret |= iqs_dis(st);
+                       ret |= iqs_dis(st, -1);
                }
                ret |= nvs_vregs_disable(&st->i2c->dev, st->vreg,
                                         ARRAY_SIZE(iqs_vregs));
@@ -969,6 +994,10 @@ static int iqs_rd(struct iqs_state *st)
                if (!st->stream)
                        /* enter stream mode on first I2C transaction */
                        iqs_wr(st, st->wr_stream);
+               if (st->dev_id == IQS_DEVID_IQS253)
+                       iqs_wr(st, st->dt_evnt253);
+               else
+                       iqs_wr(st, st->dt_evnt263);
        }
        if ((st->op_i == st->op_read_n - 1) && !st->stream)
                iqs_wr(st, st->wr_events); /* event mode at end of reads */
@@ -1121,12 +1150,19 @@ static irqreturn_t iqs_irq_thread(int irq, void *dev_id)
 static int iqs_disable(struct iqs_state *st, int snsr_id)
 {
        bool disable = true;
+       unsigned int i;
        int ret = 0;
 
        if (snsr_id >= 0) {
-               if (st->enabled & ~(1 << snsr_id)) {
+               ret = iqs_dis(st, snsr_id);
+               if (!ret)
                        st->enabled &= ~(1 << snsr_id);
+               if (st->enabled)
                        disable = false;
+       } else {
+               for (i = 0; i < IQS_DEV_N; i++) {
+                       if (st->enabled & (1 << i))
+                               iqs_dis(st, snsr_id);
                }
        }
        if (disable) {
@@ -1299,8 +1335,11 @@ static int iqs_nvs_write(void *client, int snsr_id, unsigned int nvs)
 
        case 0x12:
                val = !!val;
-               if (st->gpio_sar >= 0)
+               if (st->gpio_sar >= 0) {
                        ret = gpio_direction_output(st->gpio_sar, val);
+                       if (!ret)
+                               st->gpio_sar_val = val;
+               }
                dev_info(&st->i2c->dev,
                         "%s gpio_direction_output(gpio_sar(%d), %hhx)=%d\n",
                         __func__, st->gpio_sar, val, ret);
@@ -1396,12 +1435,24 @@ static int iqs_nvs_read(void *client, int snsr_id, char *buf)
        t += iqs_nvs_dbg_db(st, buf, t, st->dt_en_prx263);
        t += sprintf(buf + t, "IQS263 touch enable:\n");
        t += iqs_nvs_dbg_db(st, buf, t, st->dt_en_tch263);
+       t += sprintf(buf + t, "IQS263 proximity disable:\n");
+       t += iqs_nvs_dbg_db(st, buf, t, st->dt_dis_prx263);
+       t += sprintf(buf + t, "IQS263 touch disable:\n");
+       t += iqs_nvs_dbg_db(st, buf, t, st->dt_dis_tch263);
+       t += sprintf(buf + t, "IQS263 event:\n");
+       t += iqs_nvs_dbg_db(st, buf, t, st->dt_evnt263);
        t += sprintf(buf + t, "IQS253 initialization:\n");
        t += iqs_nvs_dbg_db(st, buf, t, st->dt_init253);
        t += sprintf(buf + t, "IQS253 proximity enable:\n");
        t += iqs_nvs_dbg_db(st, buf, t, st->dt_en_prx253);
        t += sprintf(buf + t, "IQS253 touch enable:\n");
        t += iqs_nvs_dbg_db(st, buf, t, st->dt_en_tch253);
+       t += sprintf(buf + t, "IQS253 proximity disable:\n");
+       t += iqs_nvs_dbg_db(st, buf, t, st->dt_dis_prx253);
+       t += sprintf(buf + t, "IQS253 touch disable:\n");
+       t += iqs_nvs_dbg_db(st, buf, t, st->dt_dis_tch253);
+       t += sprintf(buf + t, "IQS253 event:\n");
+       t += iqs_nvs_dbg_db(st, buf, t, st->dt_evnt253);
        return t;
 }
 
@@ -1603,7 +1654,6 @@ static const char *iqs_sensor_cfg_name[] = {
 
 static const struct sensor_cfg iqs_cfg_dflt = {
        .snsr_id                        = SENSOR_TYPE_PROXIMITY,
-       .no_suspend                     = true,
        .ch_n                           = 1,
        .ch_sz                          = 4,
        .part                           = IQS_NAME,
@@ -1623,6 +1673,8 @@ static const struct sensor_cfg iqs_cfg_dflt = {
        },
        .delay_us_min                   = IQS_POLL_DLY_MS_MIN * 1000,
        .delay_us_max                   = IQS_POLL_DLY_MS_MAX * 1000,
+       .flags                          = SENSOR_FLAG_ON_CHANGE_MODE |
+                                         SENSOR_FLAG_WAKE_UP,
        .thresh_lo                      = IQS_PROX_THRESHOLD,
        .thresh_hi                      = IQS_MULTI_THRESHOLD,
 };
@@ -1708,12 +1760,24 @@ static int iqs_of_dt(struct iqs_state *st, struct device_node *dn)
                                    sizeof(st->dt_en_prx263));
                ret |= iqs_of_dt_db(st, dn, "263en_touch", st->dt_en_tch263,
                                    sizeof(st->dt_en_tch263));
+               ret |= iqs_of_dt_db(st, dn, "263dis_prox", st->dt_dis_prx263,
+                                   sizeof(st->dt_dis_prx263));
+               ret |= iqs_of_dt_db(st, dn, "263dis_touch", st->dt_dis_tch263,
+                                   sizeof(st->dt_dis_tch263));
+               ret |= iqs_of_dt_db(st, dn, "263event", st->dt_evnt263,
+                                   sizeof(st->dt_evnt263));
                ret |= iqs_of_dt_db(st, dn, "253init", st->dt_init253,
                                    sizeof(st->dt_en_tch253));
                ret |= iqs_of_dt_db(st, dn, "253en_prox", st->dt_en_prx253,
                                    sizeof(st->dt_en_tch253));
                ret |= iqs_of_dt_db(st, dn, "253en_touch", st->dt_en_tch253,
                                    sizeof(st->dt_en_tch253));
+               ret |= iqs_of_dt_db(st, dn, "253dis_prox", st->dt_dis_prx253,
+                                   sizeof(st->dt_dis_tch253));
+               ret |= iqs_of_dt_db(st, dn, "253dis_touch", st->dt_dis_tch253,
+                                   sizeof(st->dt_dis_tch253));
+               ret |= iqs_of_dt_db(st, dn, "253event", st->dt_evnt253,
+                                   sizeof(st->dt_evnt253));
                if (ret)
                        return ret;
        }
@@ -1774,7 +1838,12 @@ static int iqs_probe(struct i2c_client *client, const struct i2c_device_id *id)
        st->i2c = client;
        ret = iqs_of_dt(st, client->dev.of_node);
        if (ret) {
-               dev_err(&client->dev, "%s _of_dt ERR\n", __func__);
+               if (ret == -ENODEV) {
+                       dev_info(&client->dev, "%s DT disabled\n", __func__);
+               } else {
+                       dev_err(&client->dev, "%s _of_dt ERR\n", __func__);
+                       ret = -ENODEV;
+               }
                goto iqs_probe_exit;
        }
 
@@ -1806,7 +1875,7 @@ static int iqs_probe(struct i2c_client *client, const struct i2c_device_id *id)
                                     &iqs_fn_dev, &st->cfg[i]);
                st->cfg[i].snsr_id = i;
                if (!ret) {
-                       st->prox[i].nvs_data = st->nvs_st[i];
+                       st->prox[i].nvs_st = st->nvs_st[i];
                        st->prox[i].handler = st->nvs->handler;
                        n++;
                }
@@ -1823,8 +1892,10 @@ static int iqs_probe(struct i2c_client *client, const struct i2c_device_id *id)
        if (client->irq) {
                irqflags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
                for (i = 0; i < IQS_DEV_N; i++) {
-                       if (st->cfg[i].no_suspend)
-                               irqflags |= IRQF_NO_SUSPEND;
+                       if (st->cfg[i].snsr_id >= 0) {
+                               if (st->cfg[i].flags & SENSOR_FLAG_WAKE_UP)
+                                       irqflags |= IRQF_NO_SUSPEND;
+                       }
                }
                ret = request_threaded_irq(client->irq, NULL, iqs_irq_thread,
                                           irqflags, IQS_NAME, st);
@@ -1840,8 +1911,11 @@ static int iqs_probe(struct i2c_client *client, const struct i2c_device_id *id)
        if (st->os) {
                iqs_disable(st, -1);
        } else {
-               ret = iqs_enable(st, IQS_DEV_PROX, 1);
-               ret |= iqs_enable(st, IQS_DEV_TOUCH, 1);
+               ret = 0;
+               if (st->nvs_st[IQS_DEV_PROX])
+                       ret |= iqs_enable(st, IQS_DEV_PROX, 1);
+               if (st->nvs_st[IQS_DEV_TOUCH])
+                       ret |= iqs_enable(st, IQS_DEV_TOUCH, 1);
                if (ret) {
                        iqs_err(st);
                        /* if an error then switch to OS controlled */
index 8f4bed0745286f549994d99efa329f111fec55fb..067171c4aa04cfbaa36b01d22ba02a45883cada9 100644 (file)
@@ -36,6 +36,7 @@
 #define NVS_FLOAT_SIGNIFICANCE_MICRO   (1000000) /* IIO_VAL_INT_PLUS_MICRO */
 #define NVS_FLOAT_SIGNIFICANCE_NANO    (1000000000) /* IIO_VAL_INT_PLUS_NANO */
 
+/* from AOS sensors.h */
 #define SENSOR_TYPE_ACCELEROMETER              (1)
 #define SENSOR_TYPE_MAGNETIC_FIELD             (2)
 #define SENSOR_TYPE_ORIENTATION                        (3)
 #define SENSOR_TYPE_WAKE_GESTURE               (23)
 #define SENSOR_TYPE_GLANCE_GESTURE             (24)
 #define SENSOR_TYPE_PICK_UP_GESTURE            (25)
+/* from AOS sensors.h */
+#define SENSOR_FLAG_WAKE_UP                    (0x1)
+#define SENSOR_FLAG_ON_CHANGE_MODE             (0x2)
+#define SENSOR_FLAG_ONE_SHOT_MODE              (0x4)
+#define SENSOR_FLAG_SPECIAL_REPORTING_MODE     (0x6)
+/* end AOS sensors.h */
+#define SENSOR_FLAG_NO_CFG_MASK                (0x6) /* unconfigurable flags */
 
 enum nvs_float_significance {
        NVS_FLOAT_MICRO                 = 0, /* IIO_VAL_INT_PLUS_MICRO */
@@ -76,7 +84,6 @@ struct nvs_float {
 struct sensor_cfg {
        const char *name;               /* sensor name */
        int snsr_id;                    /* sensor ID */
-       bool no_suspend;                /* true if active during suspend */
        int kbuf_sz;                    /* kernel buffer size (n bytes) */
        int timestamp_sz;               /* hub: timestamp size (n bytes) */
        int snsr_data_n;                /* hub: number of data bytes */
index 57d5831f70d3b2574024e9ddc5b179de808af352..9d04fea25ba0594cecd9f4bea57082cda3ca05f0 100644 (file)
@@ -14,7 +14,6 @@
 #ifndef _NVS_LIGHT_H_
 #define _NVS_LIGHT_H_
 
-#include <linux/iio/iio.h>
 #include <linux/of.h>
 #include <linux/nvs.h>
 
@@ -23,7 +22,6 @@
 #define RET_HW_UPDATE                  (1)
 
 #define NVS_LIGHT_STRING               "light"
-#define SENSOR_FLAG_ON_CHANGE_MODE     0x2 /* from AOS sensors.h */
 
 /**
  * struct nvs_light_dynamic - the structure that allows the NVS
@@ -108,40 +106,10 @@ struct nvs_light {
        unsigned int nld_i_hi;          /* high index limit to dynamic table */
        struct nvs_light_dynamic *nld_tbl; /* ptr to nvs_light_dynamic table */
        struct sensor_cfg *cfg;         /* pointer to sensor configuration */
-       void *nvs_data;                 /* NVS data for NVS handler */
+       void *nvs_st;                   /* NVS state data for NVS handler */
        int (*handler)(void *handle, void *buffer, s64 ts);
 };
 
-static const struct iio_chan_spec iio_chan_spec_nvs_light[] = {
-       {
-               .type                   = IIO_LIGHT,
-               .scan_type              = IIO_ST('u', 32, 32, 0),
-               .info_mask              = BIT(IIO_CHAN_INFO_RAW) |
-                                         BIT(IIO_CHAN_INFO_BATCH_FLUSH) |
-                                         BIT(IIO_CHAN_INFO_BATCH_PERIOD) |
-                                         BIT(IIO_CHAN_INFO_BATCH_TIMEOUT) |
-                                         BIT(IIO_CHAN_INFO_BATCH_FLAGS) |
-                                         BIT(IIO_CHAN_INFO_PEAK) |
-                                         BIT(IIO_CHAN_INFO_PEAK_SCALE) |
-                                         BIT(IIO_CHAN_INFO_SCALE) |
-                                         BIT(IIO_CHAN_INFO_OFFSET) |
-                                         BIT(IIO_CHAN_INFO_THRESHOLD_LOW) |
-                                         BIT(IIO_CHAN_INFO_THRESHOLD_HIGH),
-               .info_mask_separate     = BIT(IIO_CHAN_INFO_RAW) |
-                                         BIT(IIO_CHAN_INFO_BATCH_FLUSH) |
-                                         BIT(IIO_CHAN_INFO_BATCH_PERIOD) |
-                                         BIT(IIO_CHAN_INFO_BATCH_TIMEOUT) |
-                                         BIT(IIO_CHAN_INFO_BATCH_FLAGS) |
-                                         BIT(IIO_CHAN_INFO_PEAK) |
-                                         BIT(IIO_CHAN_INFO_PEAK_SCALE) |
-                                         BIT(IIO_CHAN_INFO_SCALE) |
-                                         BIT(IIO_CHAN_INFO_OFFSET) |
-                                         BIT(IIO_CHAN_INFO_THRESHOLD_LOW) |
-                                         BIT(IIO_CHAN_INFO_THRESHOLD_HIGH),
-       },
-       IIO_CHAN_SOFT_TIMESTAMP(1)
-};
-
 int nvs_light_read(struct nvs_light *nl);
 int nvs_light_enable(struct nvs_light *nl);
 int nvs_light_of_dt(struct nvs_light *nl, const struct device_node *np,
index 9be42832103cfa74e07763301885ffb1c13de62e..3c61bc1e9aded88258b1d72eb881cb01da0821da 100644 (file)
@@ -14,7 +14,6 @@
 #ifndef _NVS_PROXIMITY_H_
 #define _NVS_PROXIMITY_H_
 
-#include <linux/iio/iio.h>
 #include <linux/of.h>
 #include <linux/nvs.h>
 
@@ -23,7 +22,6 @@
 #define RET_HW_UPDATE                  (1)
 
 #define NVS_PROXIMITY_STRING           "proximity"
-#define SENSOR_FLAG_ON_CHANGE_MODE     0x2 /* from AOS sensors.h */
 
 /**
  * struct nvs_proximity - the common structure between the
@@ -77,40 +75,10 @@ struct nvs_proximity {
        unsigned int delay_us;          /* OS requested sample delay */
        unsigned int report;            /* report count */
        struct sensor_cfg *cfg;         /* pointer to sensor configuration */
-       void *nvs_data;                 /* NVS data for NVS handler */
+       void *nvs_st;                   /* NVS state data for NVS handler */
        int (*handler)(void *handle, void *buffer, s64 ts);
 };
 
-static const struct iio_chan_spec iio_chan_spec_nvs_proximity[] = {
-       {
-               .type                   = IIO_PROXIMITY,
-               .scan_type              = IIO_ST('u', 32, 32, 0),
-               .info_mask              = BIT(IIO_CHAN_INFO_RAW) |
-                                         BIT(IIO_CHAN_INFO_BATCH_FLUSH) |
-                                         BIT(IIO_CHAN_INFO_BATCH_PERIOD) |
-                                         BIT(IIO_CHAN_INFO_BATCH_TIMEOUT) |
-                                         BIT(IIO_CHAN_INFO_BATCH_FLAGS) |
-                                         BIT(IIO_CHAN_INFO_PEAK) |
-                                         BIT(IIO_CHAN_INFO_PEAK_SCALE) |
-                                         BIT(IIO_CHAN_INFO_SCALE) |
-                                         BIT(IIO_CHAN_INFO_OFFSET) |
-                                         BIT(IIO_CHAN_INFO_THRESHOLD_LOW) |
-                                         BIT(IIO_CHAN_INFO_THRESHOLD_HIGH),
-               .info_mask_separate     = BIT(IIO_CHAN_INFO_RAW) |
-                                         BIT(IIO_CHAN_INFO_BATCH_FLUSH) |
-                                         BIT(IIO_CHAN_INFO_BATCH_PERIOD) |
-                                         BIT(IIO_CHAN_INFO_BATCH_TIMEOUT) |
-                                         BIT(IIO_CHAN_INFO_BATCH_FLAGS) |
-                                         BIT(IIO_CHAN_INFO_PEAK) |
-                                         BIT(IIO_CHAN_INFO_PEAK_SCALE) |
-                                         BIT(IIO_CHAN_INFO_SCALE) |
-                                         BIT(IIO_CHAN_INFO_OFFSET) |
-                                         BIT(IIO_CHAN_INFO_THRESHOLD_LOW) |
-                                         BIT(IIO_CHAN_INFO_THRESHOLD_HIGH),
-       },
-       IIO_CHAN_SOFT_TIMESTAMP(1)
-};
-
 int nvs_proximity_enable(struct nvs_proximity *np);
 int nvs_proximity_read(struct nvs_proximity *np);
 int nvs_proximity_of_dt(struct nvs_proximity *np, const struct device_node *dn,