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