iio: proximity: configurable SAR resume
Erik Lilliebjerg [Fri, 11 Sep 2015 12:29:04 +0000 (05:29 -0700)]
- Add a device tree parameter to set the deferred resume execution delay.
  This allows no IQS device interactions when there are fast system resume
  suspends.
- Add a device tree parameter to set the SAR GPIO assertion level when the
  IQS device is configured as a non-wake device.  In other words, when the
  device is configured for sleep during suspend, this DT setting determines
  the SAR GPIO state during the suspend period.

Bug 200133919.

Change-Id: I5c26835d673b65c00742307dc9454f20baa91988
Signed-off-by: Erik Lilliebjerg <elilliebjerg@nvidia.com>
Reviewed-on: http://git-master/r/797723
(cherry picked from commit ea3ea28b324ab87139404bb26490e1f58a0653a5)
Reviewed-on: http://git-master/r/800321
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Robert Collins <rcollins@nvidia.com>
Tested-by: Robert Collins <rcollins@nvidia.com>

Documentation/devicetree/bindings/iio/iqs253-ps.txt
drivers/iio/proximity/nvs_iqs2x3.c

index 75dd54f..bd60f26 100644 (file)
@@ -241,6 +241,14 @@ Optional properties:
        SAR GPIO (according to the gpio_sar_assert_polarity) when an I2C
        transaction is about to start and deasserts when the I2C transaction
        finishes.
+- sar_suspend_assert: If the device is not configured to operate during suspend
+                      then this determines the SAR GPIO setting during suspend:
+                     -1 = DISABLE: SAR GPIO remains at current state from when
+                                   device was operational.
+                     0 = !ASSERT: GPIO is not asserted according to
+                                  gpio_sar_assert_polarity.
+                     1 = ASSERT: GPIO is asserted according to
+                                 gpio_sar_assert_polarity.
 - os_options: If the IQS device is to be controlled by the OS then set this
              value to 1.  The default is 0.
   Note: The SAR_proximity and SAR_touch sensors can still be exposed to
@@ -286,6 +294,16 @@ Optional properties:
                       status.
   Note: The watchdog timer is actually recommended by Azoteq.
        If this is not defined, the default will be 30 seconds.
+- deferred_resume_ms: The delay in milliseconds of when to execute the resume.
+                      Due to the time consumed trying to communicate with the
+                     device, suspend and resume can be adversely affected.
+                     This setting allows resume to be deferred for the amount
+                     of time specified; consider the situation where the
+                     system resumes for a very short period and then suspends
+                     again.  If this situation happened within this deferred
+                     resume time, then the whole process of resuming and
+                     suspending again would not require any communication with
+                     the device thereby not affecting the overall system.
 - i2c_retry: The number of times to try an I2C transaction before bailing.
 - gpio_rdy_retry: The number of times to try forcing a communication window.
   Note: When I2C communication is attempted outside the communication window by
index b8b700d..30ee830 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/nvs_proximity.h>
 
 
-#define IQS_DRIVER_VERSION             (14)
+#define IQS_DRIVER_VERSION             (15)
 #define IQS_VENDOR                     "Azoteq"
 #define IQS_NAME                       "iqs2x3"
 #define IQS_NAME_IQS253                        "iqs253"
@@ -466,6 +466,7 @@ struct iqs_state {
        unsigned int errs;              /* error count */
        unsigned int enabled;           /* enable status */
        unsigned int susrsm_en;         /* suspend/resume enable status */
+       unsigned int dfr_rsm_ms;        /* ms to wait before resuming */
        u16 i2c_addr;                   /* I2C address */
        u8 dev_id;                      /* device ID */
        bool irq_dis;                   /* interrupt disable flag */
@@ -488,6 +489,7 @@ struct iqs_state {
        int gpio_rdy;                   /* GPIO */
        int gpio_sar;                   /* GPIO */
        int gpio_sar_val;               /* current GPIO state */
+       int gpio_sar_sus_assrt;         /* GPIO assertion when suspending */
        unsigned int sar_assert_pol;    /* sar assert polarity */
        unsigned int gpio_sar_dev;      /* device that controls SAR GPIO */
        unsigned int msg_n;             /* I2C transaction count */
@@ -1769,11 +1771,16 @@ static int iqs_nvs_read(void *client, int snsr_id, char *buf)
                else
                        t += sprintf(buf + t, "gpio_rdy %d=%d\n", st->gpio_rdy,
                                     gpio_get_value_cansleep(st->gpio_rdy));
-               if (st->gpio_sar < 0)
+               if (st->gpio_sar < 0) {
                        t += sprintf(buf + t, "NO gpio_sar\n");
-               else
+               } else {
                        t += sprintf(buf + t, "gpio_sar %d=%d\n", st->gpio_sar,
                                     gpio_get_value_cansleep(st->gpio_sar));
+                       if (!(st->cfg->flags & SENSOR_FLAG_WAKE_UP))
+                               t += sprintf(buf + t,
+                                            "gpio_sar suspend assert=%d\n",
+                                            st->gpio_sar_sus_assrt);
+               }
                t += sprintf(buf + t, "gpio_sar_dev=%s\n",
                             iqs_sensor_cfg_name[st->gpio_sar_dev]);
                t += sprintf(buf + t, "irq=%d\n", st->i2c->irq);
@@ -1784,6 +1791,8 @@ static int iqs_nvs_read(void *client, int snsr_id, char *buf)
                             st->irq_set_irq_wake);
                t += sprintf(buf + t, "susrsm=%x\n", st->susrsm);
                t += sprintf(buf + t, "resume=%x\n", st->resume);
+               t += sprintf(buf + t, "deferred resume delay=%ums\n",
+                            st->dfr_rsm_ms);
                for (i = 0; i < IQS_DEV_N; i++)
                        t += sprintf(buf + t, "%s_binary_hw=%x\n",
                                     iqs_sensor_cfg_name[i],
@@ -1835,6 +1844,9 @@ static int iqs_suspend(struct device *dev)
                        iqs_disable(st, -1);
                }
        }
+       if (st->gpio_sar_sus_assrt >= 0 && !(st->cfg->flags &
+                                            SENSOR_FLAG_WAKE_UP))
+               iqs_gpio_sar(st, st->gpio_sar_sus_assrt);
        iqs_mutex_unlock(st);
        if (st->sts & NVS_STS_SPEW_MSG)
                dev_info(&client->dev, "%s elapsed t=%lldns  err=%d\n",
@@ -1865,7 +1877,7 @@ static int iqs_resume(struct device *dev)
                 */
                st->resume = true;
                mod_delayed_work(system_freezable_wq, &st->dw,
-                                msecs_to_jiffies(IQS_START_DELAY_MS));
+                                msecs_to_jiffies(st->dfr_rsm_ms));
        }
        iqs_mutex_unlock(st);
        if (st->sts & NVS_STS_SPEW_MSG)
@@ -2104,10 +2116,12 @@ static int iqs_of_dt(struct iqs_state *st, struct device_node *dn)
                nvs_proximity_of_dt(&st->prox[i], dn, st->cfg[i].name);
        }
        st->wd_to_ms = IQS_POLL_DLY_MS_WATCHDOG;
+       st->dfr_rsm_ms = IQS_START_DELAY_MS;
        st->i2c_retry = IQS_I2C_RETRY_N;
        st->gpio_rdy_retry = IQS_RDY_RETRY_N;
        st->gpio_rdy = -1;
        st->gpio_sar = -1;
+       st->gpio_sar_sus_assrt = -1;
        /* device tree parameters */
        if (dn) {
                /* device specific parameters */
@@ -2119,6 +2133,8 @@ static int iqs_of_dt(struct iqs_state *st, struct device_node *dn)
                                __func__, st->stream, IQS_STREAM_N - 1);
                        st->stream = IQS_STREAM_OFF;
                }
+               of_property_read_u32(dn, "deferred_resume_ms",
+                                    &st->dfr_rsm_ms);
                i = 0;
                of_property_read_u32(dn, "irq_set_irq_wake", &i);
                if (i)
@@ -2133,6 +2149,8 @@ static int iqs_of_dt(struct iqs_state *st, struct device_node *dn)
                                     &st->gpio_rdy_retry);
                of_property_read_u32(dn, "sar_assert_polarity",
                                     &st->sar_assert_pol);
+               of_property_read_s32(dn, "sar_suspend_assert",
+                                    &st->gpio_sar_sus_assrt);
                st->sar_assert_pol = !!st->sar_assert_pol;
                st->gpio_rdy = of_get_named_gpio(dn, "gpio_rdy", 0);
                st->gpio_sar = of_get_named_gpio(dn, "gpio_sar", 0);