Skip to content

Commit

Permalink
Input: iqs7222 - acknowledge reset before writing registers
Browse files Browse the repository at this point in the history
If the device suffers a spurious reset while reacting to a previous
spurious reset, the second reset interrupt is preempted because the
ACK_RESET bit is written last.

To solve this problem, write the ACK_RESET bit prior to writing any
other registers. This ensures that any registers written before the
second spurious reset will be rewritten.

Last but not least, the order in which the ACK_RESET bit is written
relative to the second filter beta register is important for select
variants of silicon. Enforce the correct order so as to not clobber
the system status register.

Fixes: e505eda ("Input: add support for Azoteq IQS7222A/B/C")
Signed-off-by: Jeff LaBundy <jeff@labundy.com>
Link: https://lore.kernel.org/r/20220626072412.475211-5-jeff@labundy.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
  • Loading branch information
Jeff LaBundy authored and Dmitry Torokhov committed Jun 27, 2022
1 parent 1e4189d commit 2e70ef5
Showing 1 changed file with 29 additions and 3 deletions.
32 changes: 29 additions & 3 deletions drivers/input/misc/iqs7222.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,11 @@ enum iqs7222_reg_key_id {

enum iqs7222_reg_grp_id {
IQS7222_REG_GRP_STAT,
IQS7222_REG_GRP_FILT,
IQS7222_REG_GRP_CYCLE,
IQS7222_REG_GRP_GLBL,
IQS7222_REG_GRP_BTN,
IQS7222_REG_GRP_CHAN,
IQS7222_REG_GRP_FILT,
IQS7222_REG_GRP_SLDR,
IQS7222_REG_GRP_GPIO,
IQS7222_REG_GRP_SYS,
Expand Down Expand Up @@ -1348,6 +1348,34 @@ static int iqs7222_dev_init(struct iqs7222_private *iqs7222, int dir)
int comms_offset = dev_desc->comms_offset;
int error, i, j, k;

/*
* Acknowledge reset before writing any registers in case the device
* suffers a spurious reset during initialization. Because this step
* may change the reserved fields of the second filter beta register,
* its cache must be updated.
*
* Writing the second filter beta register, in turn, may clobber the
* system status register. As such, the filter beta register pair is
* written first to protect against this hazard.
*/
if (dir == WRITE) {
u16 reg = dev_desc->reg_grps[IQS7222_REG_GRP_FILT].base + 1;
u16 filt_setup;

error = iqs7222_write_word(iqs7222, IQS7222_SYS_SETUP,
iqs7222->sys_setup[0] |
IQS7222_SYS_SETUP_ACK_RESET);
if (error)
return error;

error = iqs7222_read_word(iqs7222, reg, &filt_setup);
if (error)
return error;

iqs7222->filt_setup[1] &= GENMASK(7, 0);
iqs7222->filt_setup[1] |= (filt_setup & ~GENMASK(7, 0));
}

/*
* Take advantage of the stop-bit disable function, if available, to
* save the trouble of having to reopen a communication window after
Expand Down Expand Up @@ -2254,8 +2282,6 @@ static int iqs7222_parse_all(struct iqs7222_private *iqs7222)
return error;
}

sys_setup[0] |= IQS7222_SYS_SETUP_ACK_RESET;

return iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_SYS,
IQS7222_REG_KEY_NONE);
}
Expand Down

0 comments on commit 2e70ef5

Please sign in to comment.