e99aa0cdfd9b61ce773c478b9cef9d2597f14c49
[openwrt/staging/svanheule.git] /
1 From d4dd09968cab3249e6148e1c3fccb51824edb411 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?=
3 <nfraprado@collabora.com>
4 Date: Thu, 6 Jul 2023 11:37:37 -0400
5 Subject: [PATCH 30/42] thermal/drivers/mediatek/lvts_thermal: Manage threshold
6 between sensors
7 MIME-Version: 1.0
8 Content-Type: text/plain; charset=UTF-8
9 Content-Transfer-Encoding: 8bit
10
11 Each LVTS thermal controller can have up to four sensors, each capable
12 of triggering its own interrupt when its measured temperature crosses
13 the configured threshold. The threshold for each sensor is handled
14 separately by the thermal framework, since each one is registered with
15 its own thermal zone and trips. However, the temperature thresholds are
16 configured on the controller, and therefore are shared between all
17 sensors on that controller.
18
19 When the temperature measured by the sensors is different enough to
20 cause the thermal framework to configure different thresholds for each
21 one, interrupts start triggering on sensors outside the last threshold
22 configured.
23
24 To address the issue, track the thresholds required by each sensor and
25 only actually set the highest one in the hardware, and disable
26 interrupts for all sensors outside the current configured range.
27
28 Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
29 Signed-off-by: NĂ­colas F. R. A. Prado <nfraprado@collabora.com>
30 Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
31 Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
32 Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
33 Link: https://lore.kernel.org/r/20230706153823.201943-7-nfraprado@collabora.com
34 ---
35 drivers/thermal/mediatek/lvts_thermal.c | 69 +++++++++++++++++++++++++
36 1 file changed, 69 insertions(+)
37
38 --- a/drivers/thermal/mediatek/lvts_thermal.c
39 +++ b/drivers/thermal/mediatek/lvts_thermal.c
40 @@ -67,6 +67,11 @@
41 #define LVTS_CALSCALE_CONF 0x300
42 #define LVTS_MONINT_CONF 0x8300318C
43
44 +#define LVTS_MONINT_OFFSET_SENSOR0 0xC
45 +#define LVTS_MONINT_OFFSET_SENSOR1 0x180
46 +#define LVTS_MONINT_OFFSET_SENSOR2 0x3000
47 +#define LVTS_MONINT_OFFSET_SENSOR3 0x3000000
48 +
49 #define LVTS_INT_SENSOR0 0x0009001F
50 #define LVTS_INT_SENSOR1 0x001203E0
51 #define LVTS_INT_SENSOR2 0x00247C00
52 @@ -112,6 +117,8 @@ struct lvts_sensor {
53 void __iomem *base;
54 int id;
55 int dt_id;
56 + int low_thresh;
57 + int high_thresh;
58 };
59
60 struct lvts_ctrl {
61 @@ -121,6 +128,8 @@ struct lvts_ctrl {
62 int num_lvts_sensor;
63 int mode;
64 void __iomem *base;
65 + int low_thresh;
66 + int high_thresh;
67 };
68
69 struct lvts_domain {
70 @@ -292,12 +301,66 @@ static int lvts_get_temp(struct thermal_
71 return 0;
72 }
73
74 +static void lvts_update_irq_mask(struct lvts_ctrl *lvts_ctrl)
75 +{
76 + u32 masks[] = {
77 + LVTS_MONINT_OFFSET_SENSOR0,
78 + LVTS_MONINT_OFFSET_SENSOR1,
79 + LVTS_MONINT_OFFSET_SENSOR2,
80 + LVTS_MONINT_OFFSET_SENSOR3,
81 + };
82 + u32 value = 0;
83 + int i;
84 +
85 + value = readl(LVTS_MONINT(lvts_ctrl->base));
86 +
87 + for (i = 0; i < ARRAY_SIZE(masks); i++) {
88 + if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh
89 + && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh)
90 + value |= masks[i];
91 + else
92 + value &= ~masks[i];
93 + }
94 +
95 + writel(value, LVTS_MONINT(lvts_ctrl->base));
96 +}
97 +
98 +static bool lvts_should_update_thresh(struct lvts_ctrl *lvts_ctrl, int high)
99 +{
100 + int i;
101 +
102 + if (high > lvts_ctrl->high_thresh)
103 + return true;
104 +
105 + for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++)
106 + if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh
107 + && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh)
108 + return false;
109 +
110 + return true;
111 +}
112 +
113 static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
114 {
115 struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz);
116 + struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, sensors[lvts_sensor->id]);
117 void __iomem *base = lvts_sensor->base;
118 u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD);
119 u32 raw_high = lvts_temp_to_raw(high);
120 + bool should_update_thresh;
121 +
122 + lvts_sensor->low_thresh = low;
123 + lvts_sensor->high_thresh = high;
124 +
125 + should_update_thresh = lvts_should_update_thresh(lvts_ctrl, high);
126 + if (should_update_thresh) {
127 + lvts_ctrl->high_thresh = high;
128 + lvts_ctrl->low_thresh = low;
129 + }
130 + lvts_update_irq_mask(lvts_ctrl);
131 +
132 + if (!should_update_thresh)
133 + return 0;
134
135 /*
136 * Low offset temperature threshold
137 @@ -521,6 +584,9 @@ static int lvts_sensor_init(struct devic
138 */
139 lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ?
140 imm_regs[i] : msr_regs[i];
141 +
142 + lvts_sensor[i].low_thresh = INT_MIN;
143 + lvts_sensor[i].high_thresh = INT_MIN;
144 };
145
146 lvts_ctrl->num_lvts_sensor = lvts_ctrl_data->num_lvts_sensor;
147 @@ -688,6 +754,9 @@ static int lvts_ctrl_init(struct device
148 */
149 lvts_ctrl[i].hw_tshut_raw_temp =
150 lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp);
151 +
152 + lvts_ctrl[i].low_thresh = INT_MIN;
153 + lvts_ctrl[i].high_thresh = INT_MIN;
154 }
155
156 /*