Skip to content

Commit 1e4189d

Browse files
jlabundydtor
authored andcommitted
Input: iqs7222 - protect volatile registers
Select variants of silicon silently mirror part of the event mask register to the system setup register (0xD0), and vice versa. For the following sequence: 1. Read registers 0xD0 onward and store their contents. 2. Modify the contents, including event mask fields. 3. Write registers 0xD0 onward with the modified contents. 4. Write register 0xD0 on its own again later, using the contents from step 1 to populate any reserved fields. ...the event mask register (e.g. address 0xDA) has been corrupted by writing register 0xD0 with contents that were made stale after step 3. To solve this problem, read register 0xD0 once more between steps 3 and 4. When register 0xD0 is written during step 4, the portion which is mirrored to the event mask register already matches what was written in step 3. Fixes: e505eda ("Input: add support for Azoteq IQS7222A/B/C") Signed-off-by: Jeff LaBundy <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 95215d3 commit 1e4189d

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

drivers/input/misc/iqs7222.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,9 +1274,22 @@ static int iqs7222_ati_trigger(struct iqs7222_private *iqs7222)
12741274
struct i2c_client *client = iqs7222->client;
12751275
ktime_t ati_timeout;
12761276
u16 sys_status = 0;
1277-
u16 sys_setup = iqs7222->sys_setup[0] & ~IQS7222_SYS_SETUP_ACK_RESET;
1277+
u16 sys_setup;
12781278
int error, i;
12791279

1280+
/*
1281+
* The reserved fields of the system setup register may have changed
1282+
* as a result of other registers having been written. As such, read
1283+
* the register's latest value to avoid unexpected behavior when the
1284+
* register is written in the loop that follows.
1285+
*/
1286+
error = iqs7222_read_word(iqs7222, IQS7222_SYS_SETUP, &sys_setup);
1287+
if (error)
1288+
return error;
1289+
1290+
sys_setup &= ~IQS7222_SYS_SETUP_INTF_MODE_MASK;
1291+
sys_setup &= ~IQS7222_SYS_SETUP_PWR_MODE_MASK;
1292+
12801293
for (i = 0; i < IQS7222_NUM_RETRIES; i++) {
12811294
/*
12821295
* Trigger ATI from streaming and normal-power modes so that
@@ -2241,9 +2254,6 @@ static int iqs7222_parse_all(struct iqs7222_private *iqs7222)
22412254
return error;
22422255
}
22432256

2244-
sys_setup[0] &= ~IQS7222_SYS_SETUP_INTF_MODE_MASK;
2245-
sys_setup[0] &= ~IQS7222_SYS_SETUP_PWR_MODE_MASK;
2246-
22472257
sys_setup[0] |= IQS7222_SYS_SETUP_ACK_RESET;
22482258

22492259
return iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_SYS,

0 commit comments

Comments
 (0)