Skip to content

Commit 9c1d639

Browse files
Miao Lijic23
authored andcommitted
iio: light: stk3310: Deal with the ps interrupt issue in PM
On the Inspur HS326 laptop(which integrated with HiSilicon M900 processor), if the STK3311-X chip's PS interrupt is configured in "Recommended interrupt mode", the interrupt cannot be triggered normally after waking from suspend or hibernation. In this case, neither disabling and re-enabling the interrupt nor resetting the PS threshold register can restore the interrupt to normal operation. If the interrupt is disabled in suspend() then reset the PS threshold register and enable the interrupt in resume(). This resolves the issue. Signed-off-by: Miao Li <limiao@kylinos.cn> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
1 parent 11aa529 commit 9c1d639

1 file changed

Lines changed: 69 additions & 7 deletions

File tree

drivers/iio/light/stk3310.c

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ struct stk3310_data {
130130
struct mutex lock;
131131
bool als_enabled;
132132
bool ps_enabled;
133+
bool ps_int_enabled;
134+
uint32_t ps_thdl;
135+
uint32_t ps_thdh;
133136
uint32_t ps_near_level;
134137
u64 timestamp;
135138
struct regmap *regmap;
@@ -309,10 +312,17 @@ static int stk3310_write_event(struct iio_dev *indio_dev,
309312

310313
buf = cpu_to_be16(val);
311314
ret = regmap_bulk_write(data->regmap, reg, &buf, 2);
312-
if (ret < 0)
315+
if (ret < 0) {
313316
dev_err(&client->dev, "failed to set PS threshold!\n");
317+
return ret;
318+
}
314319

315-
return ret;
320+
if (reg == STK3310_REG_THDH_PS)
321+
data->ps_thdh = val;
322+
else
323+
data->ps_thdl = val;
324+
325+
return 0;
316326
}
317327

318328
static int stk3310_read_event_config(struct iio_dev *indio_dev,
@@ -344,11 +354,17 @@ static int stk3310_write_event_config(struct iio_dev *indio_dev,
344354
/* Set INT_PS value */
345355
mutex_lock(&data->lock);
346356
ret = regmap_field_write(data->reg_int_ps, state);
347-
if (ret < 0)
357+
if (ret < 0) {
348358
dev_err(&client->dev, "failed to set interrupt mode\n");
359+
mutex_unlock(&data->lock);
360+
return ret;
361+
}
362+
363+
data->ps_int_enabled = state;
364+
349365
mutex_unlock(&data->lock);
350366

351-
return ret;
367+
return 0;
352368
}
353369

354370
static int stk3310_read_raw(struct iio_dev *indio_dev,
@@ -517,10 +533,15 @@ static int stk3310_init(struct iio_dev *indio_dev)
517533

518534
/* Enable PS interrupts */
519535
ret = regmap_field_write(data->reg_int_ps, STK3310_PSINT_EN);
520-
if (ret < 0)
536+
if (ret < 0) {
521537
dev_err(&client->dev, "failed to enable interrupts!\n");
538+
return ret;
539+
}
522540

523-
return ret;
541+
data->ps_int_enabled = true;
542+
data->ps_thdh = STK3310_PS_MAX_VAL;
543+
544+
return 0;
524545
}
525546

526547
static bool stk3310_is_volatile_reg(struct device *dev, unsigned int reg)
@@ -684,24 +705,65 @@ static void stk3310_remove(struct i2c_client *client)
684705
static int stk3310_suspend(struct device *dev)
685706
{
686707
struct stk3310_data *data;
708+
int ret;
687709

688710
data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
689711

712+
if (data->ps_int_enabled) {
713+
ret = regmap_field_write(data->reg_int_ps, 0x0);
714+
if (ret < 0) {
715+
dev_err(dev, "failed to disable ps int at suspend.\n");
716+
return ret;
717+
}
718+
}
719+
690720
return stk3310_set_state(data, STK3310_STATE_STANDBY);
691721
}
692722

693723
static int stk3310_resume(struct device *dev)
694724
{
695725
u8 state = 0;
696726
struct stk3310_data *data;
727+
__be16 buf;
728+
int ret;
697729

698730
data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
699731
if (data->ps_enabled)
700732
state |= STK3310_STATE_EN_PS;
701733
if (data->als_enabled)
702734
state |= STK3310_STATE_EN_ALS;
703735

704-
return stk3310_set_state(data, state);
736+
ret = stk3310_set_state(data, state);
737+
if (ret < 0)
738+
return ret;
739+
740+
if (data->ps_thdl != 0x0) {
741+
buf = cpu_to_be16(data->ps_thdl);
742+
ret = regmap_bulk_write(data->regmap, STK3310_REG_THDL_PS, &buf, 2);
743+
if (ret < 0) {
744+
dev_err(dev, "failed to set reg THDL_PS at resume.\n");
745+
return ret;
746+
}
747+
}
748+
749+
if (data->ps_thdh != STK3310_PS_MAX_VAL) {
750+
buf = cpu_to_be16(data->ps_thdh);
751+
ret = regmap_bulk_write(data->regmap, STK3310_REG_THDH_PS, &buf, 2);
752+
if (ret < 0) {
753+
dev_err(dev, "failed to set reg THDH_PS at resume.\n");
754+
return ret;
755+
}
756+
}
757+
758+
if (data->ps_int_enabled) {
759+
ret = regmap_field_write(data->reg_int_ps, STK3310_PSINT_EN);
760+
if (ret < 0) {
761+
dev_err(dev, "failed to enable ps int at resume.\n");
762+
return ret;
763+
}
764+
}
765+
766+
return 0;
705767
}
706768

707769
static DEFINE_SIMPLE_DEV_PM_OPS(stk3310_pm_ops, stk3310_suspend,

0 commit comments

Comments
 (0)