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