drivers/iio/light/stk3310.c | 75 ++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 5 deletions(-)
From: Miao Li <limiao@kylinos.cn>
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>
---
drivers/iio/light/stk3310.c | 75 ++++++++++++++++++++++++++++++++++---
1 file changed, 70 insertions(+), 5 deletions(-)
diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c
index a75a83594..f7c4e5014 100644
--- a/drivers/iio/light/stk3310.c
+++ b/drivers/iio/light/stk3310.c
@@ -117,6 +117,9 @@ struct stk3310_data {
struct mutex lock;
bool als_enabled;
bool ps_enabled;
+ bool ps_int_enabled;
+ uint32_t ps_thdl;
+ uint32_t ps_thdh;
uint32_t ps_near_level;
u64 timestamp;
struct regmap *regmap;
@@ -296,8 +299,15 @@ static int stk3310_write_event(struct iio_dev *indio_dev,
buf = cpu_to_be16(val);
ret = regmap_bulk_write(data->regmap, reg, &buf, 2);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&client->dev, "failed to set PS threshold!\n");
+ return ret;
+ }
+
+ if (reg == STK3310_REG_THDH_PS)
+ data->ps_thdh = val;
+ else
+ data->ps_thdl = val;
return ret;
}
@@ -331,8 +341,17 @@ static int stk3310_write_event_config(struct iio_dev *indio_dev,
/* Set INT_PS value */
mutex_lock(&data->lock);
ret = regmap_field_write(data->reg_int_ps, state);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&client->dev, "failed to set interrupt mode\n");
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+
+ if (state == false)
+ data->ps_int_enabled = false;
+ else
+ data->ps_int_enabled = true;
+
mutex_unlock(&data->lock);
return ret;
@@ -504,10 +523,15 @@ static int stk3310_init(struct iio_dev *indio_dev)
/* Enable PS interrupts */
ret = regmap_field_write(data->reg_int_ps, STK3310_PSINT_EN);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&client->dev, "failed to enable interrupts!\n");
+ return ret;
+ }
- return ret;
+ data->ps_int_enabled = true;
+ data->ps_thdh = STK3310_PS_MAX_VAL;
+
+ return 0;
}
static bool stk3310_is_volatile_reg(struct device *dev, unsigned int reg)
@@ -671,9 +695,18 @@ static void stk3310_remove(struct i2c_client *client)
static int stk3310_suspend(struct device *dev)
{
struct stk3310_data *data;
+ int ret;
data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
+ if (data->ps_int_enabled) {
+ ret = regmap_field_write(data->reg_int_ps, 0x0);
+ if (ret < 0) {
+ dev_err(dev, "failed to disable ps int at suspend.\n");
+ return ret;
+ }
+ }
+
return stk3310_set_state(data, STK3310_STATE_STANDBY);
}
@@ -681,6 +714,8 @@ static int stk3310_resume(struct device *dev)
{
u8 state = 0;
struct stk3310_data *data;
+ __be16 buf;
+ int ret;
data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
if (data->ps_enabled)
@@ -688,7 +723,37 @@ static int stk3310_resume(struct device *dev)
if (data->als_enabled)
state |= STK3310_STATE_EN_ALS;
- return stk3310_set_state(data, state);
+ ret = stk3310_set_state(data, state);
+ if (ret < 0)
+ return ret;
+
+ if (data->ps_thdl != 0x0) {
+ buf = cpu_to_be16(data->ps_thdl);
+ ret = regmap_bulk_write(data->regmap, STK3310_REG_THDL_PS, &buf, sizeof(buf));
+ if (ret < 0) {
+ dev_err(dev, "failed to set reg THDL_PS at resume.\n");
+ return ret;
+ }
+ }
+
+ if (data->ps_thdh != STK3310_PS_MAX_VAL) {
+ buf = cpu_to_be16(data->ps_thdh);
+ ret = regmap_bulk_write(data->regmap, STK3310_REG_THDH_PS, &buf, sizeof(buf));
+ if (ret < 0) {
+ dev_err(dev, "failed to set reg THDH_PS at resume.\n");
+ return ret;
+ }
+ }
+
+ if (data->ps_int_enabled) {
+ ret = regmap_field_write(data->reg_int_ps, STK3310_PSINT_EN);
+ if (ret < 0) {
+ dev_err(dev, "failed to enable ps int at resume.\n");
+ return ret;
+ }
+ }
+
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(stk3310_pm_ops, stk3310_suspend,
--
2.25.1
On Wed, 29 Apr 2026 15:14:02 +0800 Miao Li <limiao870622@163.com> wrote: > From: Miao Li <limiao@kylinos.cn> > > 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> Hi. Please do not send a new version in reply to an old one. A few reasons that most kernel maintainers ask for new threads for each version. 1. Threads can get very complex if there are lots of versions. 2. Many reviewers who find themselves with a few minutes look at most recent emails. In a threaded email client, a reply like this one ends up pages back so attracts fewer reviews. I don't have anything else to add to Andy's review. However please slow down a bit on new versions to allow people to respond to earlier ones. If there is a known problem you have noticed after sending it out feel free to review your own patch on the list and point that problem out. Jonathan
On Wed, Apr 29, 2026 at 03:14:02PM +0800, Miao Li wrote: > On the Inspur HS326 laptop(which integrated with HiSilicon M900 '...laptop (which...' > 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. ... > + if (state == false) > + data->ps_int_enabled = false; > + else > + data->ps_int_enabled = true; data->ps_int_enabled = state; -- With Best Regards, Andy Shevchenko
© 2016 - 2026 Red Hat, Inc.