Skip to content

Commit 5bd36c3

Browse files
committed
iio: accel: try to fix problems with the sc7a20 accelerometer after
resume Previously, when resuming from sleep, the PineNote would emit the following stack trace caused by some kind of mishandling of the irq of the accelerometer pinenote kernel: irq 79: nobody cared (try booting with the "irqpoll" option) pinenote kernel: CPU: 0 PID: 310 Comm: irq/79-sc7a20-t Not tainted 5.17.0-rc6-next-20220304-pinenote-202307051629 #1 pinenote kernel: Hardware name: Pine64 PineNote v1.2 (DT) pinenote kernel: Call trace: pinenote kernel: dump_backtrace.part.0+0xc4/0xd0 pinenote kernel: show_stack+0x14/0x60 pinenote kernel: dump_stack_lvl+0x60/0x78 pinenote kernel: dump_stack+0x14/0x2c pinenote kernel: __report_bad_irq+0x48/0x158 pinenote kernel: note_interrupt+0x2f4/0x3f0 pinenote kernel: handle_irq_event+0xd4/0x160 pinenote kernel: handle_level_irq+0xd4/0x200 pinenote kernel: generic_handle_irq+0x2c/0x40 pinenote kernel: rockchip_irq_demux+0xa4/0x224 pinenote kernel: generic_handle_domain_irq+0x38/0x5c pinenote kernel: gic_handle_irq+0xac/0x124 pinenote kernel: call_on_irq_stack+0x2c/0x38 pinenote kernel: do_interrupt_handler+0x78/0x84 pinenote kernel: el1_interrupt+0x30/0x50 pinenote kernel: el1h_64_irq_handler+0x14/0x20 pinenote kernel: el1h_64_irq+0x64/0x68 pinenote kernel: irq_finalize_oneshot.part.0+0x94/0x160 pinenote kernel: irq_thread_fn+0x5c/0x90 pinenote kernel: irq_thread+0x170/0x21c pinenote kernel: kthread+0xd4/0xdc pinenote kernel: ret_from_fork+0x10/0x20 pinenote kernel: handlers: pinenote kernel: [<00000000117b7317>] st_sensors_irq_handler [st_sensors] threaded [<00000000e2a480c4>] st_sensors_irq_thread [st_sensors] pinenote kernel: Disabling IRQ torvalds#79 It seems that the irq handler was triggered after the actual irq was already disabled for sleep by the system, leading to the irq handler not actually handling those irqs. I may be wrong with that interpretation... Sometimes this lead to the accelerometer not working after resume. In order to prevent spurious irqs during the standby/resume cycle, explicitly turn off the device and irq during suspend, and resume by hand when the system resumes. Signed-off-by: Maximilian Weigand <mweigand@mweigand.net>
1 parent d200212 commit 5bd36c3

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

drivers/iio/accel/st_accel_i2c.c

+40
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,51 @@ static int st_accel_i2c_probe(struct i2c_client *client)
202202
return st_accel_common_probe(indio_dev);
203203
}
204204

205+
static int __maybe_unused st_accel_suspend(struct device *dev)
206+
{
207+
struct i2c_client *client = to_i2c_client(dev);
208+
struct iio_dev *indio_dev;
209+
int ret;
210+
struct st_sensor_data *sdata;
211+
212+
indio_dev = i2c_get_clientdata(client);
213+
sdata = iio_priv(indio_dev);
214+
pr_info("%s", __func__);
215+
st_sensors_set_enable(indio_dev, false);
216+
st_sensors_set_dataready_irq(indio_dev, false);
217+
disable_irq(sdata->irq);
218+
219+
return 0;
220+
}
221+
222+
static int __maybe_unused st_accel_resume(struct device *dev)
223+
{
224+
struct i2c_client *client = to_i2c_client(dev);
225+
struct iio_dev *indio_dev;
226+
struct st_sensor_data *sdata;
227+
int ret;
228+
229+
indio_dev = i2c_get_clientdata(client);
230+
sdata = iio_priv(indio_dev);
231+
232+
pr_info("%s", __func__);
233+
st_sensors_set_enable(indio_dev, true);
234+
st_sensors_set_dataready_irq(indio_dev, true);
235+
// enabling the irq here will reduce the number of spurious irqs, and the
236+
// device will keep on working after resume.
237+
// Still not enough...
238+
enable_irq(sdata->irq);
239+
return 0;
240+
}
241+
242+
static SIMPLE_DEV_PM_OPS(st_accel_pm, st_accel_suspend, st_accel_resume);
243+
205244
static struct i2c_driver st_accel_driver = {
206245
.driver = {
207246
.name = "st-accel-i2c",
208247
.of_match_table = st_accel_of_match,
209248
.acpi_match_table = st_accel_acpi_match,
249+
.pm = &st_accel_pm,
210250
},
211251
.probe = st_accel_i2c_probe,
212252
.id_table = st_accel_id_table,

drivers/iio/common/st_sensors/st_sensors_trigger.c

+10
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ static irqreturn_t st_sensors_irq_thread(int irq, void *p)
8787
st_sensors_new_samples_available(indio_dev, sdata)) {
8888
iio_trigger_poll_nested(p);
8989
} else {
90+
pr_info(
91+
"st_sensors_irq_thread: %i returning IRQ_NONE (%i/%i/%i/%u) %s",
92+
irq,
93+
sdata->hw_irq_trigger,
94+
st_sensors_new_samples_available(indio_dev, sdata),
95+
sdata->num_data_channels,
96+
sdata->odr,
97+
trig->name
98+
);
99+
/* return IRQ_HANDLED; */
90100
dev_dbg(indio_dev->dev.parent, "spurious IRQ\n");
91101
return IRQ_NONE;
92102
}

0 commit comments

Comments
 (0)