On Tue, Nov 26, 2024 at 5:21 AM Nícolas F. R. A. Prado <nfraprado@xxxxxxxxxxxxx> wrote: > > When configured in filtered mode, the LVTS thermal controller will > monitor the temperature from the sensors and trigger an interrupt once a > thermal threshold is crossed. > > Currently this is true even during suspend and resume. The problem with > that is that when enabling the internal clock of the LVTS controller in > lvts_ctrl_set_enable() during resume, the temperature reading can glitch > and appear much higher than the real one, resulting in a spurious > interrupt getting generated. > This sounds weird to me. On my end, the symptom is that the device sometimes cannot suspend. To be more precise, `echo mem > /sys/power/state` returns almost immediately. I think the irq is more likely to be triggered during suspension. > Disable the temperature monitoring and give some time for the signals to > stabilize during suspend in order to prevent such spurious interrupts. > > Cc: stable@xxxxxxxxxxxxxxx > Reported-by: Hsin-Te Yuan <yuanhsinte@xxxxxxxxxxxx> > Closes: https://lore.kernel.org/all/20241108-lvts-v1-1-eee339c6ca20@xxxxxxxxxxxx/ > Fixes: 8137bb90600d ("thermal/drivers/mediatek/lvts_thermal: Add suspend and resume") > Signed-off-by: Nícolas F. R. A. Prado <nfraprado@xxxxxxxxxxxxx> > --- > drivers/thermal/mediatek/lvts_thermal.c | 36 +++++++++++++++++++++++++++++++-- > 1 file changed, 34 insertions(+), 2 deletions(-) > > diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c > index 1997e91bb3be94a3059db619238aa5787edc7675..a92ff2325c40704adc537af6995b34f93c3b0650 100644 > --- a/drivers/thermal/mediatek/lvts_thermal.c > +++ b/drivers/thermal/mediatek/lvts_thermal.c > @@ -860,6 +860,32 @@ static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td, > return 0; > } > > +static void lvts_ctrl_monitor_enable(struct device *dev, struct lvts_ctrl *lvts_ctrl, bool enable) > +{ > + /* > + * Bitmaps to enable each sensor on filtered mode in the MONCTL0 > + * register. > + */ > + u32 sensor_filt_bitmap[] = { BIT(0), BIT(1), BIT(2), BIT(3) }; > + u32 sensor_map = 0; > + int i; > + > + if (lvts_ctrl->mode != LVTS_MSR_FILTERED_MODE) > + return; > + > + if (enable) { > + lvts_for_each_valid_sensor(i, lvts_ctrl) > + sensor_map |= sensor_filt_bitmap[i]; > + } > + > + /* > + * Bits: > + * 9: Single point access flow > + * 0-3: Enable sensing point 0-3 > + */ > + writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base)); > +} > + > /* > * At this point the configuration register is the only place in the > * driver where we write multiple values. Per hardware constraint, > @@ -1381,8 +1407,11 @@ static int lvts_suspend(struct device *dev) > > lvts_td = dev_get_drvdata(dev); > > - for (i = 0; i < lvts_td->num_lvts_ctrl; i++) > + for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { > + lvts_ctrl_monitor_enable(dev, &lvts_td->lvts_ctrl[i], false); > + usleep_range(100, 200); > lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false); > + } > > clk_disable_unprepare(lvts_td->clk); > > @@ -1400,8 +1429,11 @@ static int lvts_resume(struct device *dev) > if (ret) > return ret; > > - for (i = 0; i < lvts_td->num_lvts_ctrl; i++) > + for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { > lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], true); > + usleep_range(100, 200); > + lvts_ctrl_monitor_enable(dev, &lvts_td->lvts_ctrl[i], true); > + } > > return 0; > } > > -- > 2.47.0 >