linux-mediatek.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/6] thermal/drivers/mediatek/lvts_thermal: Fixes to the interrupt handling
@ 2023-05-04  0:48 Nícolas F. R. A. Prado
  2023-05-04  0:48 ` [PATCH v2 1/6] thermal/drivers/mediatek/lvts_thermal: Handle IRQ on all controllers Nícolas F. R. A. Prado
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Nícolas F. R. A. Prado @ 2023-05-04  0:48 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: kernel, Alexandre Mergnat, Balsam CHIHI, Chen-Yu Tsai,
	Alexandre Bailon, AngeloGioacchino Del Regno,
	Nícolas F. R. A. Prado, Amit Kucheria, Matthias Brugger,
	Rafael J. Wysocki, Zhang Rui, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-pm


Fixes in the interrupt handling of the LVTS thermal driver noticed while
testing it on the Spherion Chromebook (mt8192-asurada-spherion) with the
MT8192 support series [1].

These are standalone fixes and don't depend on anything else.

While version 1 fixed the interrupt storms that were happening, after
doing some more testing I realized that interrupts still weren't
correctly working when crossing thermal trip points, so I've added a
couple more commits to get that fixed on version 2.

[1] https://lore.kernel.org/all/20230307163413.143334-1-bchihi@baylibre.com/

Thanks,
Nícolas

Changes in v2:
- Added commits 3, 5, 6 to get working interrupts when crossing thermal
  trip points
- Updated commit 4 with interrupt flags for the offset

Nícolas F. R. A. Prado (6):
  thermal/drivers/mediatek/lvts_thermal: Handle IRQ on all controllers
  thermal/drivers/mediatek/lvts_thermal: Honor sensors in immediate mode
  thermal/drivers/mediatek/lvts_thermal: Use offset threshold for IRQ
  thermal/drivers/mediatek/lvts_thermal: Disable undesired interrupts
  thermal/drivers/mediatek/lvts_thermal: Don't leave threshold zeroed
  thermal/drivers/mediatek/lvts_thermal: Manage threshold between
    sensors

 drivers/thermal/mediatek/lvts_thermal.c | 142 ++++++++++++++++++------
 1 file changed, 110 insertions(+), 32 deletions(-)

-- 
2.40.1



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 1/6] thermal/drivers/mediatek/lvts_thermal: Handle IRQ on all controllers
  2023-05-04  0:48 [PATCH v2 0/6] thermal/drivers/mediatek/lvts_thermal: Fixes to the interrupt handling Nícolas F. R. A. Prado
@ 2023-05-04  0:48 ` Nícolas F. R. A. Prado
  2023-05-04  0:48 ` [PATCH v2 2/6] thermal/drivers/mediatek/lvts_thermal: Honor sensors in immediate mode Nícolas F. R. A. Prado
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Nícolas F. R. A. Prado @ 2023-05-04  0:48 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: kernel, Alexandre Mergnat, Balsam CHIHI, Chen-Yu Tsai,
	Alexandre Bailon, AngeloGioacchino Del Regno,
	Nícolas F. R. A. Prado, Amit Kucheria, Matthias Brugger,
	Rafael J. Wysocki, Zhang Rui, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-pm

There is a single IRQ handler for each LVTS thermal domain, and it is
supposed to check each of its underlying controllers for the origin of
the interrupt and clear its status. However due to a typo, only the
first controller was ever being handled, which resulted in the interrupt
never being cleared when it happened on the other controllers. Add the
missing index so interrupts are handled for all controllers.

Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Tested-by: Chen-Yu Tsai <wenst@chromium.org>

---

(no changes since v1)

 drivers/thermal/mediatek/lvts_thermal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c
index 3df4989f9902..2988f201633a 100644
--- a/drivers/thermal/mediatek/lvts_thermal.c
+++ b/drivers/thermal/mediatek/lvts_thermal.c
@@ -450,7 +450,7 @@ static irqreturn_t lvts_irq_handler(int irq, void *data)
 
 	for (i = 0; i < lvts_td->num_lvts_ctrl; i++) {
 
-		aux = lvts_ctrl_irq_handler(lvts_td->lvts_ctrl);
+		aux = lvts_ctrl_irq_handler(&lvts_td->lvts_ctrl[i]);
 		if (aux != IRQ_HANDLED)
 			continue;
 
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 2/6] thermal/drivers/mediatek/lvts_thermal: Honor sensors in immediate mode
  2023-05-04  0:48 [PATCH v2 0/6] thermal/drivers/mediatek/lvts_thermal: Fixes to the interrupt handling Nícolas F. R. A. Prado
  2023-05-04  0:48 ` [PATCH v2 1/6] thermal/drivers/mediatek/lvts_thermal: Handle IRQ on all controllers Nícolas F. R. A. Prado
@ 2023-05-04  0:48 ` Nícolas F. R. A. Prado
  2023-06-02  8:48   ` Daniel Lezcano
  2023-05-04  0:48 ` [PATCH v2 3/6] thermal/drivers/mediatek/lvts_thermal: Use offset threshold for IRQ Nícolas F. R. A. Prado
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 10+ messages in thread
From: Nícolas F. R. A. Prado @ 2023-05-04  0:48 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: kernel, Alexandre Mergnat, Balsam CHIHI, Chen-Yu Tsai,
	Alexandre Bailon, AngeloGioacchino Del Regno,
	Nícolas F. R. A. Prado, Amit Kucheria, Matthias Brugger,
	Rafael J. Wysocki, Zhang Rui, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-pm

Each controller can be configured to operate on immediate or filtered
mode. On filtered mode, the sensors are enabled by setting the
corresponding bits in MONCTL0, while on immediate mode, by setting
MSRCTL1.

Previously, the code would set MSRCTL1 for all four sensors when
configured to immediate mode, but given that the controller might not
have all four sensors connected, this would cause interrupts to trigger
for non-existent sensors. Fix this by handling the MSRCTL1 register
analogously to the MONCTL0: only enable the sensors that were declared.

Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Tested-by: Chen-Yu Tsai <wenst@chromium.org>
---

(no changes since v1)

 drivers/thermal/mediatek/lvts_thermal.c | 50 +++++++++++++------------
 1 file changed, 26 insertions(+), 24 deletions(-)

diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c
index 2988f201633a..f7d998a45ea0 100644
--- a/drivers/thermal/mediatek/lvts_thermal.c
+++ b/drivers/thermal/mediatek/lvts_thermal.c
@@ -922,24 +922,6 @@ static int lvts_ctrl_configure(struct device *dev, struct lvts_ctrl *lvts_ctrl)
 			LVTS_HW_FILTER << 3 | LVTS_HW_FILTER;
 	writel(value, LVTS_MSRCTL0(lvts_ctrl->base));
 
-	/*
-	 * LVTS_MSRCTL1 : Measurement control
-	 *
-	 * Bits:
-	 *
-	 * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3
-	 * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2
-	 * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1
-	 * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0
-	 *
-	 * That configuration will ignore the filtering and the delays
-	 * introduced below in MONCTL1 and MONCTL2
-	 */
-	if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) {
-		value = BIT(9) | BIT(6) | BIT(5) | BIT(4);
-		writel(value, LVTS_MSRCTL1(lvts_ctrl->base));
-	}
-
 	/*
 	 * LVTS_MONCTL1 : Period unit and group interval configuration
 	 *
@@ -1004,6 +986,8 @@ static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl)
 	struct lvts_sensor *lvts_sensors = lvts_ctrl->sensors;
 	struct thermal_zone_device *tz;
 	u32 sensor_map = 0;
+	u32 sensor_map_bits[][4] = {{BIT(4), BIT(5), BIT(6), BIT(9)},
+				    {BIT(0), BIT(1), BIT(2), BIT(3)}};
 	int i;
 
 	for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) {
@@ -1040,20 +1024,38 @@ static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl)
 		 * map, so we can enable the temperature monitoring in
 		 * the hardware thermal controller.
 		 */
-		sensor_map |= BIT(i);
+		sensor_map |= sensor_map_bits[lvts_ctrl->mode][i];
 	}
 
 	/*
-	 * Bits:
-	 *      9: Single point access flow
-	 *    0-3: Enable sensing point 0-3
-	 *
 	 * The initialization of the thermal zones give us
 	 * which sensor point to enable. If any thermal zone
 	 * was not described in the device tree, it won't be
 	 * enabled here in the sensor map.
 	 */
-	writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base));
+	if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) {
+		/*
+		 * LVTS_MSRCTL1 : Measurement control
+		 *
+		 * Bits:
+		 *
+		 * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3
+		 * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2
+		 * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1
+		 * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0
+		 *
+		 * That configuration will ignore the filtering and the delays
+		 * introduced in MONCTL1 and MONCTL2
+		 */
+		writel(sensor_map, LVTS_MSRCTL1(lvts_ctrl->base));
+	} else {
+		/*
+		 * Bits:
+		 *      9: Single point access flow
+		 *    0-3: Enable sensing point 0-3
+		 */
+		writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base));
+	}
 
 	return 0;
 }
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 3/6] thermal/drivers/mediatek/lvts_thermal: Use offset threshold for IRQ
  2023-05-04  0:48 [PATCH v2 0/6] thermal/drivers/mediatek/lvts_thermal: Fixes to the interrupt handling Nícolas F. R. A. Prado
  2023-05-04  0:48 ` [PATCH v2 1/6] thermal/drivers/mediatek/lvts_thermal: Handle IRQ on all controllers Nícolas F. R. A. Prado
  2023-05-04  0:48 ` [PATCH v2 2/6] thermal/drivers/mediatek/lvts_thermal: Honor sensors in immediate mode Nícolas F. R. A. Prado
@ 2023-05-04  0:48 ` Nícolas F. R. A. Prado
  2023-05-04  0:48 ` [PATCH v2 4/6] thermal/drivers/mediatek/lvts_thermal: Disable undesired interrupts Nícolas F. R. A. Prado
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Nícolas F. R. A. Prado @ 2023-05-04  0:48 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: kernel, Alexandre Mergnat, Balsam CHIHI, Chen-Yu Tsai,
	Alexandre Bailon, AngeloGioacchino Del Regno,
	Nícolas F. R. A. Prado, Amit Kucheria, Matthias Brugger,
	Rafael J. Wysocki, Zhang Rui, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-pm

There are two kinds of temperature monitoring interrupts available:
* High Offset, Low Offset
* Hot, Hot to normal, Cold

The code currently uses the hot/h2n/cold interrupts, however in a way
that doesn't work: the cold threshold is left uninitialized, which
prevents the other thresholds from ever triggering, and the h2n
interrupt is used as the lower threshold, which prevents the hot
interrupt from triggering again after the thresholds are updated by the
thermal framework, since a hot interrupt can only trigger again after
the hot to normal interrupt has been triggered.

But better yet than addressing those issues, is to use the high/low
offset interrupts instead. This way only two thresholds need to be
managed, which have a simpler state machine, making them a better match
to the thermal framework's high and low thresholds.

Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>

---

Changes in v2:
- Added this commit

 drivers/thermal/mediatek/lvts_thermal.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c
index f7d998a45ea0..8449ba6ca90e 100644
--- a/drivers/thermal/mediatek/lvts_thermal.c
+++ b/drivers/thermal/mediatek/lvts_thermal.c
@@ -297,9 +297,9 @@ static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
 	u32 raw_high = lvts_temp_to_raw(high);
 
 	/*
-	 * Hot to normal temperature threshold
+	 * Low offset temperature threshold
 	 *
-	 * LVTS_H2NTHRE
+	 * LVTS_OFFSETL
 	 *
 	 * Bits:
 	 *
@@ -308,13 +308,13 @@ static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
 	if (low != -INT_MAX) {
 		pr_debug("%s: Setting low limit temperature interrupt: %d\n",
 			 thermal_zone_device_type(tz), low);
-		writel(raw_low, LVTS_H2NTHRE(base));
+		writel(raw_low, LVTS_OFFSETL(base));
 	}
 
 	/*
-	 * Hot temperature threshold
+	 * High offset temperature threshold
 	 *
-	 * LVTS_HTHRE
+	 * LVTS_OFFSETH
 	 *
 	 * Bits:
 	 *
@@ -322,7 +322,7 @@ static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
 	 */
 	pr_debug("%s: Setting high limit temperature interrupt: %d\n",
 		 thermal_zone_device_type(tz), high);
-	writel(raw_high, LVTS_HTHRE(base));
+	writel(raw_high, LVTS_OFFSETH(base));
 
 	return 0;
 }
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 4/6] thermal/drivers/mediatek/lvts_thermal: Disable undesired interrupts
  2023-05-04  0:48 [PATCH v2 0/6] thermal/drivers/mediatek/lvts_thermal: Fixes to the interrupt handling Nícolas F. R. A. Prado
                   ` (2 preceding siblings ...)
  2023-05-04  0:48 ` [PATCH v2 3/6] thermal/drivers/mediatek/lvts_thermal: Use offset threshold for IRQ Nícolas F. R. A. Prado
@ 2023-05-04  0:48 ` Nícolas F. R. A. Prado
  2023-05-04  0:48 ` [PATCH v2 5/6] thermal/drivers/mediatek/lvts_thermal: Don't leave threshold zeroed Nícolas F. R. A. Prado
  2023-05-04  0:48 ` [PATCH v2 6/6] thermal/drivers/mediatek/lvts_thermal: Manage threshold between sensors Nícolas F. R. A. Prado
  5 siblings, 0 replies; 10+ messages in thread
From: Nícolas F. R. A. Prado @ 2023-05-04  0:48 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: kernel, Alexandre Mergnat, Balsam CHIHI, Chen-Yu Tsai,
	Alexandre Bailon, AngeloGioacchino Del Regno,
	Nícolas F. R. A. Prado, Amit Kucheria, Matthias Brugger,
	Rafael J. Wysocki, Zhang Rui, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-pm

Out of the many interrupts supported by the hardware, the only ones of
interest to the driver currently are:
* The temperature went over the high offset threshold, for any of the
  sensors
* The temperature went below the low offset threshold, for any of the
  sensors
* The temperature went over the stage3 threshold

These are the only thresholds configured by the driver through the
OFFSETH, OFFSETL, and PROTTC registers, respectively.

The current interrupt mask in LVTS_MONINT_CONF, enables many more
interrupts, including data ready on sensors for both filtered and
immediate mode. These are not only not handled by the driver, but they
are also triggered too often, causing unneeded overhead. Disable these
unnecessary interrupts.

The meaning of each bit can be seen in the comment describing
LVTS_MONINTST in the IRQ handler.

Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>

---

Changes in v2:
- Reworded commit and changed flag to use offset interrupts instead

 drivers/thermal/mediatek/lvts_thermal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c
index 8449ba6ca90e..efd1e938e1c2 100644
--- a/drivers/thermal/mediatek/lvts_thermal.c
+++ b/drivers/thermal/mediatek/lvts_thermal.c
@@ -63,7 +63,7 @@
 #define LVTS_HW_FILTER				0x2
 #define LVTS_TSSEL_CONF				0x13121110
 #define LVTS_CALSCALE_CONF			0x300
-#define LVTS_MONINT_CONF			0x9FBF7BDE
+#define LVTS_MONINT_CONF			0x8300318C
 
 #define LVTS_INT_SENSOR0			0x0009001F
 #define LVTS_INT_SENSOR1			0x001203E0
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 5/6] thermal/drivers/mediatek/lvts_thermal: Don't leave threshold zeroed
  2023-05-04  0:48 [PATCH v2 0/6] thermal/drivers/mediatek/lvts_thermal: Fixes to the interrupt handling Nícolas F. R. A. Prado
                   ` (3 preceding siblings ...)
  2023-05-04  0:48 ` [PATCH v2 4/6] thermal/drivers/mediatek/lvts_thermal: Disable undesired interrupts Nícolas F. R. A. Prado
@ 2023-05-04  0:48 ` Nícolas F. R. A. Prado
  2023-06-02  9:17   ` Daniel Lezcano
  2023-05-04  0:48 ` [PATCH v2 6/6] thermal/drivers/mediatek/lvts_thermal: Manage threshold between sensors Nícolas F. R. A. Prado
  5 siblings, 1 reply; 10+ messages in thread
From: Nícolas F. R. A. Prado @ 2023-05-04  0:48 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: kernel, Alexandre Mergnat, Balsam CHIHI, Chen-Yu Tsai,
	Alexandre Bailon, AngeloGioacchino Del Regno,
	Nícolas F. R. A. Prado, Amit Kucheria, Matthias Brugger,
	Rafael J. Wysocki, Zhang Rui, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-pm

The thermal framework might leave the low threshold unset if there
aren't any lower trip points. This leaves the register zeroed, which
translates to a very high temperature for the low threshold. The
interrupt for this threshold is then immediately triggered, and the
state machine gets stuck, preventing any other temperature monitoring
interrupts to ever trigger.

(The same happens by not setting the Cold or Hot to Normal thresholds
when using those)

Set the unused threshold to a valid low value. This value was chosen so
that for any valid golden temperature read from the efuse, when the
value is converted to raw and back again to milliCelsius, the result
doesn't underflow.

Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>

---

Changes in v2:
- Added this commit

 drivers/thermal/mediatek/lvts_thermal.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c
index efd1e938e1c2..951a4cb75ef6 100644
--- a/drivers/thermal/mediatek/lvts_thermal.c
+++ b/drivers/thermal/mediatek/lvts_thermal.c
@@ -82,6 +82,8 @@
 #define LVTS_HW_SHUTDOWN_MT8195		105000
 #define LVTS_HW_SHUTDOWN_MT8192		105000
 
+#define LVTS_MINIUM_THRESHOLD		20000
+
 static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT;
 static int coeff_b = LVTS_COEFF_B;
 
@@ -309,6 +311,11 @@ static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
 		pr_debug("%s: Setting low limit temperature interrupt: %d\n",
 			 thermal_zone_device_type(tz), low);
 		writel(raw_low, LVTS_OFFSETL(base));
+	} else {
+		pr_debug("%s: Setting low limit temperature to minimum\n",
+			 thermal_zone_device_type(tz));
+		raw_low = lvts_temp_to_raw(LVTS_MINIUM_THRESHOLD);
+		writel(raw_low, LVTS_OFFSETL(base));
 	}
 
 	/*
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 6/6] thermal/drivers/mediatek/lvts_thermal: Manage threshold between sensors
  2023-05-04  0:48 [PATCH v2 0/6] thermal/drivers/mediatek/lvts_thermal: Fixes to the interrupt handling Nícolas F. R. A. Prado
                   ` (4 preceding siblings ...)
  2023-05-04  0:48 ` [PATCH v2 5/6] thermal/drivers/mediatek/lvts_thermal: Don't leave threshold zeroed Nícolas F. R. A. Prado
@ 2023-05-04  0:48 ` Nícolas F. R. A. Prado
  5 siblings, 0 replies; 10+ messages in thread
From: Nícolas F. R. A. Prado @ 2023-05-04  0:48 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: kernel, Alexandre Mergnat, Balsam CHIHI, Chen-Yu Tsai,
	Alexandre Bailon, AngeloGioacchino Del Regno,
	Nícolas F. R. A. Prado, Amit Kucheria, Matthias Brugger,
	Rafael J. Wysocki, Zhang Rui, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-pm

Each LVTS thermal controller can have up to four sensors, each capable
of triggering its own interrupt when its measured temperature crosses
the configured threshold. The threshold for each sensor is handled
separately by the thermal framework, since each one is registered with
its own thermal zone and trips. However, the temperature thresholds are
configured on the controller, and therefore are shared between all
sensors on that controller.

When the temperature measured by the sensors is different enough to
cause the thermal framework to configure different thresholds for each
one, interrupts start triggering on sensors outside the last threshold
configured.

To address the issue, track the thresholds required by each sensor and
only actually set the highest one in the hardware, and disable
interrupts for all sensors outside the current configured range.

Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>

---

Changes in v2:
- Added this commit

 drivers/thermal/mediatek/lvts_thermal.c | 69 +++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c
index 951a4cb75ef6..2f37a175b1c6 100644
--- a/drivers/thermal/mediatek/lvts_thermal.c
+++ b/drivers/thermal/mediatek/lvts_thermal.c
@@ -65,6 +65,11 @@
 #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_INT_SENSOR0			0x0009001F
 #define LVTS_INT_SENSOR1			0x001203E0
 #define LVTS_INT_SENSOR2			0x00247C00
@@ -111,6 +116,8 @@ struct lvts_sensor {
 	void __iomem *base;
 	int id;
 	int dt_id;
+	int low_thresh;
+	int high_thresh;
 };
 
 struct lvts_ctrl {
@@ -120,6 +127,8 @@ struct lvts_ctrl {
 	int num_lvts_sensor;
 	int mode;
 	void __iomem *base;
+	int low_thresh;
+	int high_thresh;
 };
 
 struct lvts_domain {
@@ -291,12 +300,66 @@ static int lvts_get_temp(struct thermal_zone_device *tz, int *temp)
 	return 0;
 }
 
+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,
+	};
+	u32 value = 0;
+	int i;
+
+	value = readl(LVTS_MONINT(lvts_ctrl->base));
+
+	for (i = 0; i < ARRAY_SIZE(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];
+	}
+
+	writel(value, LVTS_MONINT(lvts_ctrl->base));
+}
+
+static bool lvts_should_update_thresh(struct lvts_ctrl *lvts_ctrl, int high)
+{
+	int i;
+
+	if (high > lvts_ctrl->high_thresh)
+		return true;
+
+	for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++)
+		if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh
+		    && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh)
+			return false;
+
+	return true;
+}
+
 static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
 {
 	struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz);
+	struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, sensors[lvts_sensor->id]);
 	void __iomem *base = lvts_sensor->base;
 	u32 raw_low = lvts_temp_to_raw(low);
 	u32 raw_high = lvts_temp_to_raw(high);
+	bool should_update_thresh;
+
+	lvts_sensor->low_thresh = low;
+	lvts_sensor->high_thresh = high;
+
+	should_update_thresh = lvts_should_update_thresh(lvts_ctrl, high);
+	if (should_update_thresh) {
+		lvts_ctrl->high_thresh = high;
+		lvts_ctrl->low_thresh = low;
+	}
+	lvts_update_irq_mask(lvts_ctrl);
+
+	if (!should_update_thresh)
+		return 0;
 
 	/*
 	 * Low offset temperature threshold
@@ -527,6 +590,9 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl,
 		 */
 		lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ?
 			imm_regs[i] : msr_regs[i];
+
+		lvts_sensor[i].low_thresh = INT_MIN;
+		lvts_sensor[i].high_thresh = INT_MIN;
 	};
 
 	lvts_ctrl->num_lvts_sensor = lvts_ctrl_data->num_lvts_sensor;
@@ -721,6 +787,9 @@ static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td,
 		 */
 		lvts_ctrl[i].hw_tshut_raw_temp =
 			lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp);
+
+		lvts_ctrl[i].low_thresh = INT_MIN;
+		lvts_ctrl[i].high_thresh = INT_MIN;
 	}
 
 	/*
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 2/6] thermal/drivers/mediatek/lvts_thermal: Honor sensors in immediate mode
  2023-05-04  0:48 ` [PATCH v2 2/6] thermal/drivers/mediatek/lvts_thermal: Honor sensors in immediate mode Nícolas F. R. A. Prado
@ 2023-06-02  8:48   ` Daniel Lezcano
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Lezcano @ 2023-06-02  8:48 UTC (permalink / raw)
  To: Nícolas F. R. A. Prado
  Cc: kernel, Alexandre Mergnat, Balsam CHIHI, Chen-Yu Tsai,
	Alexandre Bailon, AngeloGioacchino Del Regno, Amit Kucheria,
	Matthias Brugger, Rafael J. Wysocki, Zhang Rui, linux-arm-kernel,
	linux-kernel, linux-mediatek, linux-pm

On 04/05/2023 02:48, Nícolas F. R. A. Prado wrote:
> Each controller can be configured to operate on immediate or filtered
> mode. On filtered mode, the sensors are enabled by setting the
> corresponding bits in MONCTL0, while on immediate mode, by setting
> MSRCTL1.
> 
> Previously, the code would set MSRCTL1 for all four sensors when
> configured to immediate mode, but given that the controller might not
> have all four sensors connected, this would cause interrupts to trigger
> for non-existent sensors. Fix this by handling the MSRCTL1 register
> analogously to the MONCTL0: only enable the sensors that were declared.
> 
> Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
> Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> Tested-by: Chen-Yu Tsai <wenst@chromium.org>
> ---
> 
> (no changes since v1)
> 
>   drivers/thermal/mediatek/lvts_thermal.c | 50 +++++++++++++------------
>   1 file changed, 26 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c
> index 2988f201633a..f7d998a45ea0 100644
> --- a/drivers/thermal/mediatek/lvts_thermal.c
> +++ b/drivers/thermal/mediatek/lvts_thermal.c
> @@ -922,24 +922,6 @@ static int lvts_ctrl_configure(struct device *dev, struct lvts_ctrl *lvts_ctrl)
>   			LVTS_HW_FILTER << 3 | LVTS_HW_FILTER;
>   	writel(value, LVTS_MSRCTL0(lvts_ctrl->base));
>   
> -	/*
> -	 * LVTS_MSRCTL1 : Measurement control
> -	 *
> -	 * Bits:
> -	 *
> -	 * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3
> -	 * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2
> -	 * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1
> -	 * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0
> -	 *
> -	 * That configuration will ignore the filtering and the delays
> -	 * introduced below in MONCTL1 and MONCTL2
> -	 */
> -	if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) {
> -		value = BIT(9) | BIT(6) | BIT(5) | BIT(4);
> -		writel(value, LVTS_MSRCTL1(lvts_ctrl->base));
> -	}
> -
>   	/*
>   	 * LVTS_MONCTL1 : Period unit and group interval configuration
>   	 *
> @@ -1004,6 +986,8 @@ static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl)
>   	struct lvts_sensor *lvts_sensors = lvts_ctrl->sensors;
>   	struct thermal_zone_device *tz;
>   	u32 sensor_map = 0;
> +	u32 sensor_map_bits[][4] = {{BIT(4), BIT(5), BIT(6), BIT(9)},
> +				    {BIT(0), BIT(1), BIT(2), BIT(3)}};

Even correct, this initialization sounds prone to error and a bit 
obfuscating (eg. it assumes LVTS_MSR_IMMEDIATE_MODE is 1).

What about?

	/*
	 * A description
	 */
	u32 sensor_imm_bitmap[] = { BIT(0), BIT(1), BIT(2), BIT(3) };
	u32 sensor_filt_bitmap[] = { BIT(4), BIT(5), BIT(6), BIT(9) };

	u32 *sensor_bitmap = lvts_ctrl->mode ? LVTS_MSR_IMMEDIATE_MODE : 
sensor_imm_bitmap : sensor_filt_bitmap;

>   	int i;
>   
>   	for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) {
> @@ -1040,20 +1024,38 @@ static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl)
>   		 * map, so we can enable the temperature monitoring in
>   		 * the hardware thermal controller.
>   		 */
> -		sensor_map |= BIT(i);
> +		sensor_map |= sensor_map_bits[lvts_ctrl->mode][i];

		sensor_map |= sensor_bitmap[i];
>   	}
>   
>   	/*
> -	 * Bits:
> -	 *      9: Single point access flow
> -	 *    0-3: Enable sensing point 0-3
> -	 *
>   	 * The initialization of the thermal zones give us
>   	 * which sensor point to enable. If any thermal zone
>   	 * was not described in the device tree, it won't be
>   	 * enabled here in the sensor map.
>   	 */
> -	writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base));
> +	if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) {
> +		/*
> +		 * LVTS_MSRCTL1 : Measurement control
> +		 *
> +		 * Bits:
> +		 *
> +		 * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3
> +		 * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2
> +		 * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1
> +		 * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0
> +		 *
> +		 * That configuration will ignore the filtering and the delays
> +		 * introduced in MONCTL1 and MONCTL2
> +		 */
> +		writel(sensor_map, LVTS_MSRCTL1(lvts_ctrl->base));
> +	} else {
> +		/*
> +		 * Bits:
> +		 *      9: Single point access flow
> +		 *    0-3: Enable sensing point 0-3
> +		 */
> +		writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base));
> +	}
>   
>   	return 0;
>   }

-- 
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 5/6] thermal/drivers/mediatek/lvts_thermal: Don't leave threshold zeroed
  2023-05-04  0:48 ` [PATCH v2 5/6] thermal/drivers/mediatek/lvts_thermal: Don't leave threshold zeroed Nícolas F. R. A. Prado
@ 2023-06-02  9:17   ` Daniel Lezcano
  2023-06-29 21:10     ` Nícolas F. R. A. Prado
  0 siblings, 1 reply; 10+ messages in thread
From: Daniel Lezcano @ 2023-06-02  9:17 UTC (permalink / raw)
  To: Nícolas F. R. A. Prado
  Cc: kernel, Alexandre Mergnat, Balsam CHIHI, Chen-Yu Tsai,
	Alexandre Bailon, AngeloGioacchino Del Regno, Amit Kucheria,
	Matthias Brugger, Rafael J. Wysocki, Zhang Rui, linux-arm-kernel,
	linux-kernel, linux-mediatek, linux-pm

On 04/05/2023 02:48, Nícolas F. R. A. Prado wrote:
> The thermal framework might leave the low threshold unset if there
> aren't any lower trip points. This leaves the register zeroed, which
> translates to a very high temperature for the low threshold. The
> interrupt for this threshold is then immediately triggered, and the
> state machine gets stuck, preventing any other temperature monitoring
> interrupts to ever trigger.
> 
> (The same happens by not setting the Cold or Hot to Normal thresholds
> when using those)
> 
> Set the unused threshold to a valid low value. This value was chosen so
> that for any valid golden temperature read from the efuse, when the
> value is converted to raw and back again to milliCelsius, the result
> doesn't underflow.
> 
> Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
> Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
> 
> ---
> 
> Changes in v2:
> - Added this commit
> 
>   drivers/thermal/mediatek/lvts_thermal.c | 7 +++++++
>   1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c
> index efd1e938e1c2..951a4cb75ef6 100644
> --- a/drivers/thermal/mediatek/lvts_thermal.c
> +++ b/drivers/thermal/mediatek/lvts_thermal.c
> @@ -82,6 +82,8 @@
>   #define LVTS_HW_SHUTDOWN_MT8195		105000
>   #define LVTS_HW_SHUTDOWN_MT8192		105000
>   
> +#define LVTS_MINIUM_THRESHOLD		20000

MINIMUM

So if the thermal zone reaches 20°C, the interrupt fires, the set_trips 
sets again 20°C but the interrupt won't fire until the temperature goes 
above 20°C and then crosses the temperature low threshold the way down 
again?

>   static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT;
>   static int coeff_b = LVTS_COEFF_B;
>   
> @@ -309,6 +311,11 @@ static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
>   		pr_debug("%s: Setting low limit temperature interrupt: %d\n",
>   			 thermal_zone_device_type(tz), low);
>   		writel(raw_low, LVTS_OFFSETL(base));
> +	} else {
> +		pr_debug("%s: Setting low limit temperature to minimum\n",
> +			 thermal_zone_device_type(tz));
> +		raw_low = lvts_temp_to_raw(LVTS_MINIUM_THRESHOLD);
> +		writel(raw_low, LVTS_OFFSETL(base));

That's duplicate code:

u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : 
LVTS_MINIMUM_THRESHOLD);

And then the condition in the code goes away:
         if (low != -INT_MAX) {
	}

>   	}
>   
>   	/*

-- 
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 5/6] thermal/drivers/mediatek/lvts_thermal: Don't leave threshold zeroed
  2023-06-02  9:17   ` Daniel Lezcano
@ 2023-06-29 21:10     ` Nícolas F. R. A. Prado
  0 siblings, 0 replies; 10+ messages in thread
From: Nícolas F. R. A. Prado @ 2023-06-29 21:10 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: kernel, Alexandre Mergnat, Balsam CHIHI, Chen-Yu Tsai,
	Alexandre Bailon, AngeloGioacchino Del Regno, Amit Kucheria,
	Matthias Brugger, Rafael J. Wysocki, Zhang Rui, linux-arm-kernel,
	linux-kernel, linux-mediatek, linux-pm

On Fri, Jun 02, 2023 at 11:17:27AM +0200, Daniel Lezcano wrote:
> On 04/05/2023 02:48, Nícolas F. R. A. Prado wrote:
> > The thermal framework might leave the low threshold unset if there
> > aren't any lower trip points. This leaves the register zeroed, which
> > translates to a very high temperature for the low threshold. The
> > interrupt for this threshold is then immediately triggered, and the
> > state machine gets stuck, preventing any other temperature monitoring
> > interrupts to ever trigger.
> > 
> > (The same happens by not setting the Cold or Hot to Normal thresholds
> > when using those)
> > 
> > Set the unused threshold to a valid low value. This value was chosen so
> > that for any valid golden temperature read from the efuse, when the
> > value is converted to raw and back again to milliCelsius, the result
> > doesn't underflow.
> > 
> > Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
> > Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
> > 
> > ---
> > 
> > Changes in v2:
> > - Added this commit
> > 
> >   drivers/thermal/mediatek/lvts_thermal.c | 7 +++++++
> >   1 file changed, 7 insertions(+)
> > 
> > diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c
> > index efd1e938e1c2..951a4cb75ef6 100644
> > --- a/drivers/thermal/mediatek/lvts_thermal.c
> > +++ b/drivers/thermal/mediatek/lvts_thermal.c
> > @@ -82,6 +82,8 @@
> >   #define LVTS_HW_SHUTDOWN_MT8195		105000
> >   #define LVTS_HW_SHUTDOWN_MT8192		105000
> > +#define LVTS_MINIUM_THRESHOLD		20000
> 
> MINIMUM
> 
> So if the thermal zone reaches 20°C, the interrupt fires, the set_trips sets
> again 20°C but the interrupt won't fire until the temperature goes above
> 20°C and then crosses the temperature low threshold the way down again?

Well, actually, set_trips won't even be called since from the thermal
framework's perspective we haven't crossed trip points, ie in
__thermal_zone_set_trips():

	/* No need to change trip points */
	if (tz->prev_low_trip == low && tz->prev_high_trip == high)
		return;

But in any case, yes, the interrupt will fire, the temperature will get updated
in the framework, and that's it. It will only fire again when a threshold is
crossed again (either by the temperature rising and falling again below this
minimum, or rising beyond the high treshold).

So basically at most this will cause a spurious interrupt when the temperature
gets low enough. I do get 34-36C on all sensors when idling though, so I doubt
that temperature is even reachable. Besides, we don't really have another option
here if we want working interrupts, the threshold needs to be set to a valid
value, and this is the lowest I've found.

And thanks for all the feedback! I'll prepare a v3 based on your comments.

Thanks,
Nícolas


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2023-06-29 21:10 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-04  0:48 [PATCH v2 0/6] thermal/drivers/mediatek/lvts_thermal: Fixes to the interrupt handling Nícolas F. R. A. Prado
2023-05-04  0:48 ` [PATCH v2 1/6] thermal/drivers/mediatek/lvts_thermal: Handle IRQ on all controllers Nícolas F. R. A. Prado
2023-05-04  0:48 ` [PATCH v2 2/6] thermal/drivers/mediatek/lvts_thermal: Honor sensors in immediate mode Nícolas F. R. A. Prado
2023-06-02  8:48   ` Daniel Lezcano
2023-05-04  0:48 ` [PATCH v2 3/6] thermal/drivers/mediatek/lvts_thermal: Use offset threshold for IRQ Nícolas F. R. A. Prado
2023-05-04  0:48 ` [PATCH v2 4/6] thermal/drivers/mediatek/lvts_thermal: Disable undesired interrupts Nícolas F. R. A. Prado
2023-05-04  0:48 ` [PATCH v2 5/6] thermal/drivers/mediatek/lvts_thermal: Don't leave threshold zeroed Nícolas F. R. A. Prado
2023-06-02  9:17   ` Daniel Lezcano
2023-06-29 21:10     ` Nícolas F. R. A. Prado
2023-05-04  0:48 ` [PATCH v2 6/6] thermal/drivers/mediatek/lvts_thermal: Manage threshold between sensors Nícolas F. R. A. Prado

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).