Skip to content

Commit 2bba1ac

Browse files
nfrapradodlezcano
authored andcommitted
thermal/drivers/mediatek/lvts_thermal: Manage threshold between sensors
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: f5f633b ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver") Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com> Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20230706153823.201943-7-nfraprado@collabora.com
1 parent 77354ea commit 2bba1ac

1 file changed

Lines changed: 69 additions & 0 deletions

File tree

drivers/thermal/mediatek/lvts_thermal.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@
6767
#define LVTS_CALSCALE_CONF 0x300
6868
#define LVTS_MONINT_CONF 0x8300318C
6969

70+
#define LVTS_MONINT_OFFSET_SENSOR0 0xC
71+
#define LVTS_MONINT_OFFSET_SENSOR1 0x180
72+
#define LVTS_MONINT_OFFSET_SENSOR2 0x3000
73+
#define LVTS_MONINT_OFFSET_SENSOR3 0x3000000
74+
7075
#define LVTS_INT_SENSOR0 0x0009001F
7176
#define LVTS_INT_SENSOR1 0x001203E0
7277
#define LVTS_INT_SENSOR2 0x00247C00
@@ -112,6 +117,8 @@ struct lvts_sensor {
112117
void __iomem *base;
113118
int id;
114119
int dt_id;
120+
int low_thresh;
121+
int high_thresh;
115122
};
116123

117124
struct lvts_ctrl {
@@ -121,6 +128,8 @@ struct lvts_ctrl {
121128
int num_lvts_sensor;
122129
int mode;
123130
void __iomem *base;
131+
int low_thresh;
132+
int high_thresh;
124133
};
125134

126135
struct lvts_domain {
@@ -292,12 +301,66 @@ static int lvts_get_temp(struct thermal_zone_device *tz, int *temp)
292301
return 0;
293302
}
294303

304+
static void lvts_update_irq_mask(struct lvts_ctrl *lvts_ctrl)
305+
{
306+
u32 masks[] = {
307+
LVTS_MONINT_OFFSET_SENSOR0,
308+
LVTS_MONINT_OFFSET_SENSOR1,
309+
LVTS_MONINT_OFFSET_SENSOR2,
310+
LVTS_MONINT_OFFSET_SENSOR3,
311+
};
312+
u32 value = 0;
313+
int i;
314+
315+
value = readl(LVTS_MONINT(lvts_ctrl->base));
316+
317+
for (i = 0; i < ARRAY_SIZE(masks); i++) {
318+
if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh
319+
&& lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh)
320+
value |= masks[i];
321+
else
322+
value &= ~masks[i];
323+
}
324+
325+
writel(value, LVTS_MONINT(lvts_ctrl->base));
326+
}
327+
328+
static bool lvts_should_update_thresh(struct lvts_ctrl *lvts_ctrl, int high)
329+
{
330+
int i;
331+
332+
if (high > lvts_ctrl->high_thresh)
333+
return true;
334+
335+
for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++)
336+
if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh
337+
&& lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh)
338+
return false;
339+
340+
return true;
341+
}
342+
295343
static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
296344
{
297345
struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz);
346+
struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, sensors[lvts_sensor->id]);
298347
void __iomem *base = lvts_sensor->base;
299348
u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD);
300349
u32 raw_high = lvts_temp_to_raw(high);
350+
bool should_update_thresh;
351+
352+
lvts_sensor->low_thresh = low;
353+
lvts_sensor->high_thresh = high;
354+
355+
should_update_thresh = lvts_should_update_thresh(lvts_ctrl, high);
356+
if (should_update_thresh) {
357+
lvts_ctrl->high_thresh = high;
358+
lvts_ctrl->low_thresh = low;
359+
}
360+
lvts_update_irq_mask(lvts_ctrl);
361+
362+
if (!should_update_thresh)
363+
return 0;
301364

302365
/*
303366
* Low offset temperature threshold
@@ -521,6 +584,9 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl,
521584
*/
522585
lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ?
523586
imm_regs[i] : msr_regs[i];
587+
588+
lvts_sensor[i].low_thresh = INT_MIN;
589+
lvts_sensor[i].high_thresh = INT_MIN;
524590
};
525591

526592
lvts_ctrl->num_lvts_sensor = lvts_ctrl_data->num_lvts_sensor;
@@ -688,6 +754,9 @@ static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td,
688754
*/
689755
lvts_ctrl[i].hw_tshut_raw_temp =
690756
lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp);
757+
758+
lvts_ctrl[i].low_thresh = INT_MIN;
759+
lvts_ctrl[i].high_thresh = INT_MIN;
691760
}
692761

693762
/*

0 commit comments

Comments
 (0)