thermal/intel/intel_soc_dts_iosf: Use Intel TCC library
[platform/kernel/linux-starfive.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 = tzd->devdata;
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 = tzd->devdata;
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(tzd->devdata, 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;
190
191         dts = tzd->devdata;
192
193         *type = dts->trip_types[trip];
194
195         return 0;
196 }
197
198 static int sys_get_curr_temp(struct thermal_zone_device *tzd,
199                              int *temp)
200 {
201         int status;
202         u32 out;
203         struct intel_soc_dts_sensor_entry *dts;
204         struct intel_soc_dts_sensors *sensors;
205         unsigned long raw;
206
207         dts = tzd->devdata;
208         sensors = dts->sensors;
209         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
210                                SOC_DTS_OFFSET_TEMP, &out);
211         if (status)
212                 return status;
213
214         raw = out;
215         out = bitmap_get_value8(&raw, dts->id * 8) - SOC_DTS_TJMAX_ENCODING;
216         *temp = sensors->tj_max - out * 1000;
217
218         return 0;
219 }
220
221 static struct thermal_zone_device_ops tzone_ops = {
222         .get_temp = sys_get_curr_temp,
223         .get_trip_temp = sys_get_trip_temp,
224         .get_trip_type = sys_get_trip_type,
225         .set_trip_temp = sys_set_trip_temp,
226 };
227
228 static int soc_dts_enable(int id)
229 {
230         u32 out;
231         int ret;
232
233         ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
234                             SOC_DTS_OFFSET_ENABLE, &out);
235         if (ret)
236                 return ret;
237
238         if (!(out & BIT(id))) {
239                 out |= BIT(id);
240                 ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
241                                      SOC_DTS_OFFSET_ENABLE, out);
242                 if (ret)
243                         return ret;
244         }
245
246         return ret;
247 }
248
249 static void remove_dts_thermal_zone(struct intel_soc_dts_sensor_entry *dts)
250 {
251         if (dts) {
252                 iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
253                                SOC_DTS_OFFSET_ENABLE, dts->store_status);
254                 thermal_zone_device_unregister(dts->tzone);
255         }
256 }
257
258 static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts,
259                                 bool notification_support, int trip_cnt,
260                                 int read_only_trip_cnt)
261 {
262         char name[10];
263         unsigned long trip;
264         int trip_count = 0;
265         int trip_mask = 0;
266         int writable_trip_cnt = 0;
267         unsigned long ptps;
268         u32 store_ptps;
269         unsigned long i;
270         int ret;
271
272         /* Store status to restor on exit */
273         ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
274                             SOC_DTS_OFFSET_ENABLE, &dts->store_status);
275         if (ret)
276                 goto err_ret;
277
278         dts->id = id;
279         if (notification_support) {
280                 trip_count = min(SOC_MAX_DTS_TRIPS, trip_cnt);
281                 writable_trip_cnt = trip_count - read_only_trip_cnt;
282                 trip_mask = GENMASK(writable_trip_cnt - 1, 0);
283         }
284
285         /* Check if the writable trip we provide is not used by BIOS */
286         ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
287                             SOC_DTS_OFFSET_PTPS, &store_ptps);
288         if (ret)
289                 trip_mask = 0;
290         else {
291                 ptps = store_ptps;
292                 for_each_set_clump8(i, trip, &ptps, writable_trip_cnt * 8)
293                         trip_mask &= ~BIT(i / 8);
294         }
295         dts->trip_mask = trip_mask;
296         dts->trip_count = trip_count;
297         snprintf(name, sizeof(name), "soc_dts%d", id);
298         dts->tzone = thermal_zone_device_register(name,
299                                                   trip_count,
300                                                   trip_mask,
301                                                   dts, &tzone_ops,
302                                                   NULL, 0, 0);
303         if (IS_ERR(dts->tzone)) {
304                 ret = PTR_ERR(dts->tzone);
305                 goto err_ret;
306         }
307         ret = thermal_zone_device_enable(dts->tzone);
308         if (ret)
309                 goto err_enable;
310
311         ret = soc_dts_enable(id);
312         if (ret)
313                 goto err_enable;
314
315         return 0;
316 err_enable:
317         thermal_zone_device_unregister(dts->tzone);
318 err_ret:
319         return ret;
320 }
321
322 int intel_soc_dts_iosf_add_read_only_critical_trip(
323         struct intel_soc_dts_sensors *sensors, int critical_offset)
324 {
325         int i, j;
326
327         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
328                 struct intel_soc_dts_sensor_entry *entry = &sensors->soc_dts[i];
329                 int temp = sensors->tj_max - critical_offset;
330                 unsigned long count = entry->trip_count;
331                 unsigned long mask = entry->trip_mask;
332
333                 j = find_first_zero_bit(&mask, count);
334                 if (j < count)
335                         return update_trip_temp(entry, j, temp, THERMAL_TRIP_CRITICAL);
336         }
337
338         return -EINVAL;
339 }
340 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_add_read_only_critical_trip);
341
342 void intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors *sensors)
343 {
344         u32 sticky_out;
345         int status;
346         u32 ptmc_out;
347         unsigned long flags;
348
349         spin_lock_irqsave(&sensors->intr_notify_lock, flags);
350
351         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
352                                SOC_DTS_OFFSET_PTMC, &ptmc_out);
353         ptmc_out |= SOC_DTS_PTMC_APIC_DEASSERT_BIT;
354         status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
355                                 SOC_DTS_OFFSET_PTMC, ptmc_out);
356
357         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
358                                SOC_DTS_OFFSET_PTTSS, &sticky_out);
359         pr_debug("status %d PTTSS %x\n", status, sticky_out);
360         if (sticky_out & SOC_DTS_TRIP_MASK) {
361                 int i;
362                 /* reset sticky bit */
363                 status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
364                                         SOC_DTS_OFFSET_PTTSS, sticky_out);
365                 spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
366
367                 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
368                         pr_debug("TZD update for zone %d\n", i);
369                         thermal_zone_device_update(sensors->soc_dts[i].tzone,
370                                                    THERMAL_EVENT_UNSPECIFIED);
371                 }
372         } else
373                 spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
374 }
375 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_interrupt_handler);
376
377 struct intel_soc_dts_sensors *intel_soc_dts_iosf_init(
378         enum intel_soc_dts_interrupt_type intr_type, int trip_count,
379         int read_only_trip_count)
380 {
381         struct intel_soc_dts_sensors *sensors;
382         bool notification;
383         u32 tj_max;
384         int ret;
385         int i;
386
387         if (!iosf_mbi_available())
388                 return ERR_PTR(-ENODEV);
389
390         if (!trip_count || read_only_trip_count > trip_count)
391                 return ERR_PTR(-EINVAL);
392
393         tj_max = intel_tcc_get_tjmax(-1);
394         if (tj_max < 0)
395                 return ERR_PTR(tj_max);
396
397         sensors = kzalloc(sizeof(*sensors), GFP_KERNEL);
398         if (!sensors)
399                 return ERR_PTR(-ENOMEM);
400
401         spin_lock_init(&sensors->intr_notify_lock);
402         mutex_init(&sensors->dts_update_lock);
403         sensors->intr_type = intr_type;
404         sensors->tj_max = tj_max;
405         if (intr_type == INTEL_SOC_DTS_INTERRUPT_NONE)
406                 notification = false;
407         else
408                 notification = true;
409         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
410                 sensors->soc_dts[i].sensors = sensors;
411                 ret = add_dts_thermal_zone(i, &sensors->soc_dts[i],
412                                            notification, trip_count,
413                                            read_only_trip_count);
414                 if (ret)
415                         goto err_free;
416         }
417
418         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
419                 ret = update_trip_temp(&sensors->soc_dts[i], 0, 0,
420                                        THERMAL_TRIP_PASSIVE);
421                 if (ret)
422                         goto err_remove_zone;
423
424                 ret = update_trip_temp(&sensors->soc_dts[i], 1, 0,
425                                        THERMAL_TRIP_PASSIVE);
426                 if (ret)
427                         goto err_remove_zone;
428         }
429
430         return sensors;
431 err_remove_zone:
432         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i)
433                 remove_dts_thermal_zone(&sensors->soc_dts[i]);
434
435 err_free:
436         kfree(sensors);
437         return ERR_PTR(ret);
438 }
439 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_init);
440
441 void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors)
442 {
443         int i;
444
445         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
446                 update_trip_temp(&sensors->soc_dts[i], 0, 0, 0);
447                 update_trip_temp(&sensors->soc_dts[i], 1, 0, 0);
448                 remove_dts_thermal_zone(&sensors->soc_dts[i]);
449         }
450         kfree(sensors);
451 }
452 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_exit);
453
454 MODULE_IMPORT_NS(INTEL_TCC);
455 MODULE_LICENSE("GPL v2");