| From stable+bounces-178000-greg=kroah.com@vger.kernel.org Sat Sep 6 22:20:36 2025 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Sat, 6 Sep 2025 16:19:21 -0400 |
| Subject: thermal/drivers/mediatek/lvts: Disable low offset IRQ for minimum threshold |
| To: stable@vger.kernel.org |
| Cc: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>, "AngeloGioacchino Del Regno" <angelogioacchino.delregno@collabora.com>, "Daniel Lezcano" <daniel.lezcano@linaro.org>, "Sasha Levin" <sashal@kernel.org> |
| Message-ID: <20250906201921.261506-1-sashal@kernel.org> |
| |
| From: NÃcolas F. R. A. Prado <nfraprado@collabora.com> |
| |
| [ Upstream commit fa17ff8e325a657c84be1083f06e54ee7eea82e4 ] |
| |
| In order to get working interrupts, a low offset value needs to be |
| configured. The minimum value for it is 20 Celsius, which is what is |
| configured when there's no lower thermal trip (ie the thermal core |
| passes -INT_MAX as low trip temperature). However, when the temperature |
| gets that low and fluctuates around that value it causes an interrupt |
| storm. |
| |
| Prevent that interrupt storm by not enabling the low offset interrupt if |
| the low threshold is the minimum one. |
| |
| Cc: stable@vger.kernel.org |
| Fixes: 77354eaef821 ("thermal/drivers/mediatek/lvts_thermal: Don't leave threshold zeroed") |
| Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> |
| Signed-off-by: NÃcolas F. R. A. Prado <nfraprado@collabora.com> |
| Link: https://lore.kernel.org/r/20250113-mt8192-lvts-filtered-suspend-fix-v2-3-07a25200c7c6@collabora.com |
| Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> |
| [ Adapted interrupt mask definitions ] |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/thermal/mediatek/lvts_thermal.c | 50 +++++++++++++++++++++++--------- |
| 1 file changed, 36 insertions(+), 14 deletions(-) |
| |
| --- a/drivers/thermal/mediatek/lvts_thermal.c |
| +++ b/drivers/thermal/mediatek/lvts_thermal.c |
| @@ -67,10 +67,14 @@ |
| #define LVTS_CALSCALE_CONF 0x300 |
| #define LVTS_MONINT_CONF 0x8300318C |
| |
| -#define LVTS_MONINT_OFFSET_SENSOR0 0xC |
| -#define LVTS_MONINT_OFFSET_SENSOR1 0x180 |
| -#define LVTS_MONINT_OFFSET_SENSOR2 0x3000 |
| -#define LVTS_MONINT_OFFSET_SENSOR3 0x3000000 |
| +#define LVTS_MONINT_OFFSET_HIGH_INTEN_SENSOR0 BIT(3) |
| +#define LVTS_MONINT_OFFSET_HIGH_INTEN_SENSOR1 BIT(8) |
| +#define LVTS_MONINT_OFFSET_HIGH_INTEN_SENSOR2 BIT(13) |
| +#define LVTS_MONINT_OFFSET_HIGH_INTEN_SENSOR3 BIT(25) |
| +#define LVTS_MONINT_OFFSET_LOW_INTEN_SENSOR0 BIT(2) |
| +#define LVTS_MONINT_OFFSET_LOW_INTEN_SENSOR1 BIT(7) |
| +#define LVTS_MONINT_OFFSET_LOW_INTEN_SENSOR2 BIT(12) |
| +#define LVTS_MONINT_OFFSET_LOW_INTEN_SENSOR3 BIT(24) |
| |
| #define LVTS_INT_SENSOR0 0x0009001F |
| #define LVTS_INT_SENSOR1 0x001203E0 |
| @@ -308,23 +312,41 @@ static int lvts_get_temp(struct thermal_ |
| |
| static void lvts_update_irq_mask(struct lvts_ctrl *lvts_ctrl) |
| { |
| - u32 masks[] = { |
| - LVTS_MONINT_OFFSET_SENSOR0, |
| - LVTS_MONINT_OFFSET_SENSOR1, |
| - LVTS_MONINT_OFFSET_SENSOR2, |
| - LVTS_MONINT_OFFSET_SENSOR3, |
| + static const u32 high_offset_inten_masks[] = { |
| + LVTS_MONINT_OFFSET_HIGH_INTEN_SENSOR0, |
| + LVTS_MONINT_OFFSET_HIGH_INTEN_SENSOR1, |
| + LVTS_MONINT_OFFSET_HIGH_INTEN_SENSOR2, |
| + LVTS_MONINT_OFFSET_HIGH_INTEN_SENSOR3, |
| + }; |
| + static const u32 low_offset_inten_masks[] = { |
| + LVTS_MONINT_OFFSET_LOW_INTEN_SENSOR0, |
| + LVTS_MONINT_OFFSET_LOW_INTEN_SENSOR1, |
| + LVTS_MONINT_OFFSET_LOW_INTEN_SENSOR2, |
| + LVTS_MONINT_OFFSET_LOW_INTEN_SENSOR3, |
| }; |
| u32 value = 0; |
| int i; |
| |
| value = readl(LVTS_MONINT(lvts_ctrl->base)); |
| |
| - for (i = 0; i < ARRAY_SIZE(masks); i++) { |
| + for (i = 0; i < ARRAY_SIZE(high_offset_inten_masks); i++) { |
| if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh |
| - && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh) |
| - value |= masks[i]; |
| - else |
| - value &= ~masks[i]; |
| + && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh) { |
| + /* |
| + * The minimum threshold needs to be configured in the |
| + * OFFSETL register to get working interrupts, but we |
| + * don't actually want to generate interrupts when |
| + * crossing it. |
| + */ |
| + if (lvts_ctrl->low_thresh == -INT_MAX) { |
| + value &= ~low_offset_inten_masks[i]; |
| + value |= high_offset_inten_masks[i]; |
| + } else { |
| + value |= low_offset_inten_masks[i] | high_offset_inten_masks[i]; |
| + } |
| + } else { |
| + value &= ~(low_offset_inten_masks[i] | high_offset_inten_masks[i]); |
| + } |
| } |
| |
| writel(value, LVTS_MONINT(lvts_ctrl->base)); |