]> Git Repo - J-linux.git/blob - drivers/thermal/intel/intel_soc_dts_iosf.c
Merge tag 'amd-drm-next-6.5-2023-06-09' of https://gitlab.freedesktop.org/agd5f/linux...
[J-linux.git] / drivers / thermal / intel / intel_soc_dts_iosf.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * intel_soc_dts_iosf.c
4  * Copyright (c) 2015, Intel Corporation.
5  */
6
7 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8
9 #include <linux/bitops.h>
10 #include <linux/intel_tcc.h>
11 #include <linux/module.h>
12 #include <linux/slab.h>
13 #include <linux/interrupt.h>
14 #include <asm/iosf_mbi.h>
15 #include "intel_soc_dts_iosf.h"
16
17 #define SOC_DTS_OFFSET_ENABLE           0xB0
18 #define SOC_DTS_OFFSET_TEMP             0xB1
19
20 #define SOC_DTS_OFFSET_PTPS             0xB2
21 #define SOC_DTS_OFFSET_PTTS             0xB3
22 #define SOC_DTS_OFFSET_PTTSS            0xB4
23 #define SOC_DTS_OFFSET_PTMC             0x80
24 #define SOC_DTS_TE_AUX0                 0xB5
25 #define SOC_DTS_TE_AUX1                 0xB6
26
27 #define SOC_DTS_AUX0_ENABLE_BIT         BIT(0)
28 #define SOC_DTS_AUX1_ENABLE_BIT         BIT(1)
29 #define SOC_DTS_CPU_MODULE0_ENABLE_BIT  BIT(16)
30 #define SOC_DTS_CPU_MODULE1_ENABLE_BIT  BIT(17)
31 #define SOC_DTS_TE_SCI_ENABLE           BIT(9)
32 #define SOC_DTS_TE_SMI_ENABLE           BIT(10)
33 #define SOC_DTS_TE_MSI_ENABLE           BIT(11)
34 #define SOC_DTS_TE_APICA_ENABLE         BIT(14)
35 #define SOC_DTS_PTMC_APIC_DEASSERT_BIT  BIT(4)
36
37 /* DTS encoding for TJ MAX temperature */
38 #define SOC_DTS_TJMAX_ENCODING          0x7F
39
40 /* Only 2 out of 4 is allowed for OSPM */
41 #define SOC_MAX_DTS_TRIPS               2
42
43 /* Mask for two trips in status bits */
44 #define SOC_DTS_TRIP_MASK               0x03
45
46 /* DTS0 and DTS 1 */
47 #define SOC_MAX_DTS_SENSORS             2
48
49 static int sys_get_trip_temp(struct thermal_zone_device *tzd, int trip,
50                              int *temp)
51 {
52         int status;
53         u32 out;
54         struct intel_soc_dts_sensor_entry *dts;
55         struct intel_soc_dts_sensors *sensors;
56
57         dts = thermal_zone_device_priv(tzd);
58         sensors = dts->sensors;
59         mutex_lock(&sensors->dts_update_lock);
60         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
61                                SOC_DTS_OFFSET_PTPS, &out);
62         mutex_unlock(&sensors->dts_update_lock);
63         if (status)
64                 return status;
65
66         out = (out >> (trip * 8)) & SOC_DTS_TJMAX_ENCODING;
67         if (!out)
68                 *temp = 0;
69         else
70                 *temp = sensors->tj_max - out * 1000;
71
72         return 0;
73 }
74
75 static int update_trip_temp(struct intel_soc_dts_sensor_entry *dts,
76                             int thres_index, int temp,
77                             enum thermal_trip_type trip_type)
78 {
79         int status;
80         u32 temp_out;
81         u32 out;
82         unsigned long update_ptps;
83         u32 store_ptps;
84         u32 store_ptmc;
85         u32 store_te_out;
86         u32 te_out;
87         u32 int_enable_bit = SOC_DTS_TE_APICA_ENABLE;
88         struct intel_soc_dts_sensors *sensors = dts->sensors;
89
90         if (sensors->intr_type == INTEL_SOC_DTS_INTERRUPT_MSI)
91                 int_enable_bit |= SOC_DTS_TE_MSI_ENABLE;
92
93         temp_out = (sensors->tj_max - temp) / 1000;
94
95         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
96                                SOC_DTS_OFFSET_PTPS, &store_ptps);
97         if (status)
98                 return status;
99
100         update_ptps = store_ptps;
101         bitmap_set_value8(&update_ptps, temp_out & 0xFF, thres_index * 8);
102         out = update_ptps;
103
104         status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
105                                 SOC_DTS_OFFSET_PTPS, out);
106         if (status)
107                 return status;
108
109         pr_debug("update_trip_temp PTPS = %x\n", out);
110         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
111                                SOC_DTS_OFFSET_PTMC, &out);
112         if (status)
113                 goto err_restore_ptps;
114
115         store_ptmc = out;
116
117         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
118                                SOC_DTS_TE_AUX0 + thres_index,
119                                &te_out);
120         if (status)
121                 goto err_restore_ptmc;
122
123         store_te_out = te_out;
124         /* Enable for CPU module 0 and module 1 */
125         out |= (SOC_DTS_CPU_MODULE0_ENABLE_BIT |
126                                         SOC_DTS_CPU_MODULE1_ENABLE_BIT);
127         if (temp) {
128                 if (thres_index)
129                         out |= SOC_DTS_AUX1_ENABLE_BIT;
130                 else
131                         out |= SOC_DTS_AUX0_ENABLE_BIT;
132                 te_out |= int_enable_bit;
133         } else {
134                 if (thres_index)
135                         out &= ~SOC_DTS_AUX1_ENABLE_BIT;
136                 else
137                         out &= ~SOC_DTS_AUX0_ENABLE_BIT;
138                 te_out &= ~int_enable_bit;
139         }
140         status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
141                                 SOC_DTS_OFFSET_PTMC, out);
142         if (status)
143                 goto err_restore_te_out;
144
145         status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
146                                 SOC_DTS_TE_AUX0 + thres_index,
147                                 te_out);
148         if (status)
149                 goto err_restore_te_out;
150
151         dts->trip_types[thres_index] = trip_type;
152
153         return 0;
154 err_restore_te_out:
155         iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
156                        SOC_DTS_OFFSET_PTMC, store_te_out);
157 err_restore_ptmc:
158         iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
159                        SOC_DTS_OFFSET_PTMC, store_ptmc);
160 err_restore_ptps:
161         iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
162                        SOC_DTS_OFFSET_PTPS, store_ptps);
163         /* Nothing we can do if restore fails */
164
165         return status;
166 }
167
168 static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
169                              int temp)
170 {
171         struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_priv(tzd);
172         struct intel_soc_dts_sensors *sensors = dts->sensors;
173         int status;
174
175         if (temp > sensors->tj_max)
176                 return -EINVAL;
177
178         mutex_lock(&sensors->dts_update_lock);
179         status = update_trip_temp(dts, trip, temp,
180                                   dts->trip_types[trip]);
181         mutex_unlock(&sensors->dts_update_lock);
182
183         return status;
184 }
185
186 static int sys_get_trip_type(struct thermal_zone_device *tzd,
187                              int trip, enum thermal_trip_type *type)
188 {
189         struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_priv(tzd);
190
191         *type = dts->trip_types[trip];
192
193         return 0;
194 }
195
196 static int sys_get_curr_temp(struct thermal_zone_device *tzd,
197                              int *temp)
198 {
199         int status;
200         u32 out;
201         struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_priv(tzd);
202         struct intel_soc_dts_sensors *sensors;
203         unsigned long raw;
204
205         sensors = dts->sensors;
206         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
207                                SOC_DTS_OFFSET_TEMP, &out);
208         if (status)
209                 return status;
210
211         raw = out;
212         out = bitmap_get_value8(&raw, dts->id * 8) - SOC_DTS_TJMAX_ENCODING;
213         *temp = sensors->tj_max - out * 1000;
214
215         return 0;
216 }
217
218 static struct thermal_zone_device_ops tzone_ops = {
219         .get_temp = sys_get_curr_temp,
220         .get_trip_temp = sys_get_trip_temp,
221         .get_trip_type = sys_get_trip_type,
222         .set_trip_temp = sys_set_trip_temp,
223 };
224
225 static int soc_dts_enable(int id)
226 {
227         u32 out;
228         int ret;
229
230         ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
231                             SOC_DTS_OFFSET_ENABLE, &out);
232         if (ret)
233                 return ret;
234
235         if (!(out & BIT(id))) {
236                 out |= BIT(id);
237                 ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
238                                      SOC_DTS_OFFSET_ENABLE, out);
239                 if (ret)
240                         return ret;
241         }
242
243         return ret;
244 }
245
246 static void remove_dts_thermal_zone(struct intel_soc_dts_sensor_entry *dts)
247 {
248         if (dts) {
249                 iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
250                                SOC_DTS_OFFSET_ENABLE, dts->store_status);
251                 thermal_zone_device_unregister(dts->tzone);
252         }
253 }
254
255 static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts,
256                                 bool notification_support, int trip_cnt,
257                                 int read_only_trip_cnt)
258 {
259         char name[10];
260         unsigned long trip;
261         int trip_count = 0;
262         int trip_mask = 0;
263         int writable_trip_cnt = 0;
264         unsigned long ptps;
265         u32 store_ptps;
266         unsigned long i;
267         int ret;
268
269         /* Store status to restor on exit */
270         ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
271                             SOC_DTS_OFFSET_ENABLE, &dts->store_status);
272         if (ret)
273                 goto err_ret;
274
275         dts->id = id;
276         if (notification_support) {
277                 trip_count = min(SOC_MAX_DTS_TRIPS, trip_cnt);
278                 writable_trip_cnt = trip_count - read_only_trip_cnt;
279                 trip_mask = GENMASK(writable_trip_cnt - 1, 0);
280         }
281
282         /* Check if the writable trip we provide is not used by BIOS */
283         ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
284                             SOC_DTS_OFFSET_PTPS, &store_ptps);
285         if (ret)
286                 trip_mask = 0;
287         else {
288                 ptps = store_ptps;
289                 for_each_set_clump8(i, trip, &ptps, writable_trip_cnt * 8)
290                         trip_mask &= ~BIT(i / 8);
291         }
292         dts->trip_mask = trip_mask;
293         dts->trip_count = trip_count;
294         snprintf(name, sizeof(name), "soc_dts%d", id);
295         dts->tzone = thermal_zone_device_register(name,
296                                                   trip_count,
297                                                   trip_mask,
298                                                   dts, &tzone_ops,
299                                                   NULL, 0, 0);
300         if (IS_ERR(dts->tzone)) {
301                 ret = PTR_ERR(dts->tzone);
302                 goto err_ret;
303         }
304         ret = thermal_zone_device_enable(dts->tzone);
305         if (ret)
306                 goto err_enable;
307
308         ret = soc_dts_enable(id);
309         if (ret)
310                 goto err_enable;
311
312         return 0;
313 err_enable:
314         thermal_zone_device_unregister(dts->tzone);
315 err_ret:
316         return ret;
317 }
318
319 int intel_soc_dts_iosf_add_read_only_critical_trip(
320         struct intel_soc_dts_sensors *sensors, int critical_offset)
321 {
322         int i, j;
323
324         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
325                 struct intel_soc_dts_sensor_entry *entry = &sensors->soc_dts[i];
326                 int temp = sensors->tj_max - critical_offset;
327                 unsigned long count = entry->trip_count;
328                 unsigned long mask = entry->trip_mask;
329
330                 j = find_first_zero_bit(&mask, count);
331                 if (j < count)
332                         return update_trip_temp(entry, j, temp, THERMAL_TRIP_CRITICAL);
333         }
334
335         return -EINVAL;
336 }
337 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_add_read_only_critical_trip);
338
339 void intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors *sensors)
340 {
341         u32 sticky_out;
342         int status;
343         u32 ptmc_out;
344         unsigned long flags;
345
346         spin_lock_irqsave(&sensors->intr_notify_lock, flags);
347
348         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
349                                SOC_DTS_OFFSET_PTMC, &ptmc_out);
350         ptmc_out |= SOC_DTS_PTMC_APIC_DEASSERT_BIT;
351         status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
352                                 SOC_DTS_OFFSET_PTMC, ptmc_out);
353
354         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
355                                SOC_DTS_OFFSET_PTTSS, &sticky_out);
356         pr_debug("status %d PTTSS %x\n", status, sticky_out);
357         if (sticky_out & SOC_DTS_TRIP_MASK) {
358                 int i;
359                 /* reset sticky bit */
360                 status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
361                                         SOC_DTS_OFFSET_PTTSS, sticky_out);
362                 spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
363
364                 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
365                         pr_debug("TZD update for zone %d\n", i);
366                         thermal_zone_device_update(sensors->soc_dts[i].tzone,
367                                                    THERMAL_EVENT_UNSPECIFIED);
368                 }
369         } else
370                 spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
371 }
372 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_interrupt_handler);
373
374 struct intel_soc_dts_sensors *intel_soc_dts_iosf_init(
375         enum intel_soc_dts_interrupt_type intr_type, int trip_count,
376         int read_only_trip_count)
377 {
378         struct intel_soc_dts_sensors *sensors;
379         bool notification;
380         int tj_max;
381         int ret;
382         int i;
383
384         if (!iosf_mbi_available())
385                 return ERR_PTR(-ENODEV);
386
387         if (!trip_count || read_only_trip_count > trip_count)
388                 return ERR_PTR(-EINVAL);
389
390         tj_max = intel_tcc_get_tjmax(-1);
391         if (tj_max < 0)
392                 return ERR_PTR(tj_max);
393
394         sensors = kzalloc(sizeof(*sensors), GFP_KERNEL);
395         if (!sensors)
396                 return ERR_PTR(-ENOMEM);
397
398         spin_lock_init(&sensors->intr_notify_lock);
399         mutex_init(&sensors->dts_update_lock);
400         sensors->intr_type = intr_type;
401         sensors->tj_max = tj_max;
402         if (intr_type == INTEL_SOC_DTS_INTERRUPT_NONE)
403                 notification = false;
404         else
405                 notification = true;
406         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
407                 sensors->soc_dts[i].sensors = sensors;
408                 ret = add_dts_thermal_zone(i, &sensors->soc_dts[i],
409                                            notification, trip_count,
410                                            read_only_trip_count);
411                 if (ret)
412                         goto err_free;
413         }
414
415         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
416                 ret = update_trip_temp(&sensors->soc_dts[i], 0, 0,
417                                        THERMAL_TRIP_PASSIVE);
418                 if (ret)
419                         goto err_remove_zone;
420
421                 ret = update_trip_temp(&sensors->soc_dts[i], 1, 0,
422                                        THERMAL_TRIP_PASSIVE);
423                 if (ret)
424                         goto err_remove_zone;
425         }
426
427         return sensors;
428 err_remove_zone:
429         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i)
430                 remove_dts_thermal_zone(&sensors->soc_dts[i]);
431
432 err_free:
433         kfree(sensors);
434         return ERR_PTR(ret);
435 }
436 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_init);
437
438 void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors)
439 {
440         int i;
441
442         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
443                 update_trip_temp(&sensors->soc_dts[i], 0, 0, 0);
444                 update_trip_temp(&sensors->soc_dts[i], 1, 0, 0);
445                 remove_dts_thermal_zone(&sensors->soc_dts[i]);
446         }
447         kfree(sensors);
448 }
449 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_exit);
450
451 MODULE_IMPORT_NS(INTEL_TCC);
452 MODULE_LICENSE("GPL v2");
This page took 0.056367 seconds and 4 git commands to generate.