iio: proximity: SAR v.21
Erik Lilliebjerg [Wed, 2 Dec 2015 01:07:13 +0000 (18:07 -0700)]
- Add device tree byte streams for external state low and high.
  When an external entity writes a status state to the SAR driver's external
  function sar_external_status, the corresponding DT byte stream is executed
  depending on the value written (0 or 1).
- Update documentation that explains this.

Bug 200137195

Change-Id: Ie1e3dd606f764d9cafa1b6bc170f46e86206a5f6
Signed-off-by: Erik Lilliebjerg <elilliebjerg@nvidia.com>
Reviewed-on: http://git-master/r/840111
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Wayne Hsu <wahsu@nvidia.com>
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 0a5c380..cf730f7 100644 (file)
@@ -47,7 +47,7 @@ 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 four commands: initialization, enable,
+accomplished. Currently there are four main 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.
@@ -90,6 +90,15 @@ The suspend command allows any necessary action whenever the driver receives
 notification of a suspend:
        263suspend_?
        253suspend_?
+The external state is the sar_external_status function that an external driver
+can call to notify the IQS driver of an external status.  It's purpose is for
+WARs and is therefore defined by the WAR implemented in the device tree byte
+stream "external_lo" and "external_hi" when the external state transitions to
+low and high respectively.
+       263external_lo_?
+       253external_lo_?
+       263external_hi_?
+       253external_hi_?
 
 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
@@ -126,6 +135,8 @@ where XX = part device ID (0x29=IQS253, 0x3C=IQS263)
           4: event
           5: suspend
           6: delta (see delta options far below)
+          7: external state low
+          8: external state high
           If YY is 0, then all the commands will be displayed.
       ZZ = device
           Possible devices are:
@@ -171,15 +182,12 @@ switches the gpio_rdy GPIO to input.
 toggles SAR GPIO status message spew.
 #echo 0x18 > nvs
 toggles external state status message spew.
-The external state is the sar_external_status function that an external driver
-can call to notify the IQS driver of an external status.  It's purpose is for
-WARs and is therefore defined by the WAR implemented.
 
 For overall status information:
 #echo 10 > nvs
 #cat nvs
 The results will be something like:
-       IQS driver v. 20
+       IQS driver v. 21
        ATI redo count=0
        os_options=0
        stream_mode=2
index 833c6db..9087544 100644 (file)
@@ -35,7 +35,7 @@
 #include <asm/atomic.h>
 
 
-#define IQS_DRIVER_VERSION             (20)
+#define IQS_DRIVER_VERSION             (21)
 #define IQS_VENDOR                     "Azoteq"
 #define IQS_NAME                       "iqs2x3"
 #define IQS_NAME_IQS253                        "iqs253"
@@ -159,6 +159,8 @@ enum IQS_DB_CMD {
        IQS_DB_CMD_EVNT,
        IQS_DB_CMD_SUSPND,
        IQS_DB_CMD_DELTA,
+       IQS_DB_CMD_EXT_LO,
+       IQS_DB_CMD_EXT_HI,
        IQS_DB_CMD_N,
 };
 
@@ -292,8 +294,11 @@ struct iqs_hal {
 #define IQS263_BI_ACTIVE_CH            (IQS263_BI_GESTURE_TIMERS + \
                                         IQS263_RL_GESTURE_TIMERS + 1)
 #define IQS263_RL_ACTIVE_CH            (1)
-#define IQS263_BI_N                    (IQS263_BI_ACTIVE_CH + \
+#define IQS263_BI_ENG                  (IQS263_BI_ACTIVE_CH + \
                                         IQS263_RL_ACTIVE_CH + 1)
+#define IQS263_RL_ENG                  (1)
+#define IQS263_BI_N                    (IQS263_BI_ENG + \
+                                        IQS263_RL_ENG + 1)
 /* IQS253 */
 #define IQS253_BI_SYSFLAGS             (IQS_BI_DEVINF + \
                                         IQS_RL_DEVINF + 1)
@@ -343,6 +348,7 @@ static const struct iqs_hal const iqs263_hal_tbl[] = {
        { 0x0B, IQS263_RL_TIMINGS, IQS263_BI_TIMINGS, true, },
        { 0x0C, IQS263_RL_GESTURE_TIMERS, IQS263_BI_GESTURE_TIMERS, true, },
        { 0x0D, IQS263_RL_ACTIVE_CH, IQS263_BI_ACTIVE_CH, true, },
+       { 0x48, IQS263_RL_ENG, IQS263_BI_ENG, true, },
 };
 
 static const struct iqs_hal const iqs253_hal_tbl[] = {
@@ -359,9 +365,10 @@ static const struct iqs_hal const iqs253_hal_tbl[] = {
 
 #define IQS_DT_INIT_N                  (96) /* max DT init bytes */
 #define IQS_DT_ABLE_N                  (32) /* max DT en/dis-able bytes */
-#define IQS_DT_EVNT_N                  (32) /* max DT en/dis-able bytes */
+#define IQS_DT_EVNT_N                  (32) /* max DT event bytes */
+#define IQS_DT_EXT_N                   (32) /* max DT external state bytes */
 #define IQS_DT_SUSPND_N                        (64) /* max DT suspend bytes */
-#define IQS263_MSG_N                   (14)
+#define IQS263_MSG_N                   (15)
 #define IQS253_MSG_N                   (9)
 
 #if IQS263_MSG_N < IQS253_MSG_N
@@ -581,6 +588,8 @@ struct iqs_state {
        unsigned char dt_dis[IQS_PART_N][IQS_DEV_HW_N][IQS_DT_ABLE_N]; /* " */
        unsigned char dt_evnt[IQS_PART_N][IQS_DT_EVNT_N]; /* DT byte stream */
        unsigned char dt_suspnd[IQS_PART_N][IQS_DT_SUSPND_N]; /* " */
+       unsigned char dt_ext_lo[IQS_PART_N][IQS_DT_EXT_N]; /* DT byte stream */
+       unsigned char dt_ext_hi[IQS_PART_N][IQS_DT_EXT_N]; /* DT byte stream */
        u8 rc[IQS_BI_N];                /* register cache */
        u16 *delta_avg[IQS_CH_N];       /* delta moving average data */
        struct iqs_delta_tst delta_tst[IQS_DELTA_TEST0_N][IQS_DELTA_TEST1_N];
@@ -1426,8 +1435,14 @@ static int iqs_rd(struct iqs_state *st, bool poll)
                iqs_i2c_rd(st, st->op_read_reg[i], 0);
        ret = iqs_i2c(st, true);
 #else /* IQS_I2C_M_NO_RD_ACK */
-       if (atomic_xchg(&iqs_ext_sts_chg, 0))
-               iqs_ati_redo(st);
+       if (atomic_xchg(&iqs_ext_sts_chg, 0)) {
+               /* DT WAR action based on external state */
+               if (iqs_ext_sts)
+                       iqs_wr(st, st->dt_ext_hi[st->part_i]);
+               else
+                       iqs_wr(st, st->dt_ext_lo[st->part_i]);
+               st->op_i = st->op_read_n; /* restart cycle */
+       }
        st->op_i++;
        if (st->op_i >= st->op_read_n) {
                st->op_i = 0; /* restart read cycle */
@@ -2061,6 +2076,16 @@ static int iqs_nvs_read(void *client, int snsr_id, char *buf)
                                     iqs_i2c_device_id[i].name);
                        t += iqs_nvs_dbg_db(st, buf, t, st->dt_suspnd[i]);
                }
+               if (cmd == IQS_DB_CMD_EXT_LO || !cmd) {
+                       t += sprintf(buf + t, "%s external_lo:\n",
+                                    iqs_i2c_device_id[i].name);
+                       t += iqs_nvs_dbg_db(st, buf, t, st->dt_ext_lo[i]);
+               }
+               if (cmd == IQS_DB_CMD_EXT_HI || !cmd) {
+                       t += sprintf(buf + t, "%s external_hi:\n",
+                                    iqs_i2c_device_id[i].name);
+                       t += iqs_nvs_dbg_db(st, buf, t, st->dt_ext_hi[i]);
+               }
                break;
 
        default:
@@ -2581,6 +2606,12 @@ static int iqs_of_dt(struct iqs_state *st, struct device_node *dn)
                        sprintf(str, "%uevent", part);
                        ret |= iqs_of_dt_db(st, dn, str, st->dt_evnt[i],
                                            IQS_DT_EVNT_N);
+                       sprintf(str, "%uexternal_lo", part);
+                       ret |= iqs_of_dt_db(st, dn, str, st->dt_ext_lo[i],
+                                           IQS_DT_EXT_N);
+                       sprintf(str, "%uexternal_hi", part);
+                       ret |= iqs_of_dt_db(st, dn, str, st->dt_ext_hi[i],
+                                           IQS_DT_EXT_N);
                        sprintf(str, "%ususpend", part);
                        ret |= iqs_of_dt_db(st, dn, str, st->dt_suspnd[i],
                                            IQS_DT_SUSPND_N);