2 * intel_soc_dts_thermal.c
3 * Copyright (c) 2014, Intel Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18 #include <linux/module.h>
19 #include <linux/slab.h>
20 #include <linux/interrupt.h>
21 #include <linux/thermal.h>
22 #include <asm/cpu_device_id.h>
23 #include <asm/iosf_mbi.h>
25 #define SOC_DTS_OFFSET_ENABLE 0xB0
26 #define SOC_DTS_OFFSET_TEMP 0xB1
28 #define SOC_DTS_OFFSET_PTPS 0xB2
29 #define SOC_DTS_OFFSET_PTTS 0xB3
30 #define SOC_DTS_OFFSET_PTTSS 0xB4
31 #define SOC_DTS_OFFSET_PTMC 0x80
32 #define SOC_DTS_TE_AUX0 0xB5
33 #define SOC_DTS_TE_AUX1 0xB6
35 #define SOC_DTS_AUX0_ENABLE_BIT BIT(0)
36 #define SOC_DTS_AUX1_ENABLE_BIT BIT(1)
37 #define SOC_DTS_CPU_MODULE0_ENABLE_BIT BIT(16)
38 #define SOC_DTS_CPU_MODULE1_ENABLE_BIT BIT(17)
39 #define SOC_DTS_TE_SCI_ENABLE BIT(9)
40 #define SOC_DTS_TE_SMI_ENABLE BIT(10)
41 #define SOC_DTS_TE_MSI_ENABLE BIT(11)
42 #define SOC_DTS_TE_APICA_ENABLE BIT(14)
43 #define SOC_DTS_PTMC_APIC_DEASSERT_BIT BIT(4)
45 /* DTS encoding for TJ MAX temperature */
46 #define SOC_DTS_TJMAX_ENCODING 0x7F
48 /* IRQ 86 is a fixed APIC interrupt for BYT DTS Aux threshold notifications */
49 #define BYT_SOC_DTS_APIC_IRQ 86
51 /* Only 2 out of 4 is allowed for OSPM */
52 #define SOC_MAX_DTS_TRIPS 2
54 /* Mask for two trips in status bits */
55 #define SOC_DTS_TRIP_MASK 0x03
58 #define SOC_MAX_DTS_SENSORS 2
60 #define CRITICAL_OFFSET_FROM_TJ_MAX 5000
62 struct soc_sensor_entry
{
68 struct thermal_zone_device
*tzone
;
71 static struct soc_sensor_entry
*soc_dts
[SOC_MAX_DTS_SENSORS
];
73 static int crit_offset
= CRITICAL_OFFSET_FROM_TJ_MAX
;
74 module_param(crit_offset
, int, 0644);
75 MODULE_PARM_DESC(crit_offset
,
76 "Critical Temperature offset from tj max in millidegree Celsius.");
78 static DEFINE_MUTEX(aux_update_mutex
);
79 static spinlock_t intr_notify_lock
;
80 static int soc_dts_thres_irq
;
82 static int get_tj_max(u32
*tj_max
)
88 err
= rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET
, &eax
, &edx
);
92 val
= (eax
>> 16) & 0xff;
108 static int sys_get_trip_temp(struct thermal_zone_device
*tzd
,
109 int trip
, unsigned long *temp
)
113 struct soc_sensor_entry
*aux_entry
;
115 aux_entry
= tzd
->devdata
;
118 /* Just return the critical temp */
119 *temp
= aux_entry
->tj_max
- crit_offset
;
123 mutex_lock(&aux_update_mutex
);
124 status
= iosf_mbi_read(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_READ
,
125 SOC_DTS_OFFSET_PTPS
, &out
);
126 mutex_unlock(&aux_update_mutex
);
130 out
= (out
>> (trip
* 8)) & SOC_DTS_TJMAX_ENCODING
;
135 *temp
= aux_entry
->tj_max
- out
* 1000;
140 static int update_trip_temp(struct soc_sensor_entry
*aux_entry
,
141 int thres_index
, unsigned long temp
)
151 u32 int_enable_bit
= SOC_DTS_TE_APICA_ENABLE
|
152 SOC_DTS_TE_MSI_ENABLE
;
154 temp_out
= (aux_entry
->tj_max
- temp
) / 1000;
156 status
= iosf_mbi_read(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_READ
,
157 SOC_DTS_OFFSET_PTPS
, &store_ptps
);
161 out
= (store_ptps
& ~(0xFF << (thres_index
* 8)));
162 out
|= (temp_out
& 0xFF) << (thres_index
* 8);
163 status
= iosf_mbi_write(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_WRITE
,
164 SOC_DTS_OFFSET_PTPS
, out
);
167 pr_debug("update_trip_temp PTPS = %x\n", out
);
168 status
= iosf_mbi_read(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_READ
,
169 SOC_DTS_OFFSET_PTMC
, &out
);
171 goto err_restore_ptps
;
175 status
= iosf_mbi_read(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_READ
,
176 SOC_DTS_TE_AUX0
+ thres_index
,
179 goto err_restore_ptmc
;
181 store_te_out
= te_out
;
183 /* Enable for CPU module 0 and module 1 */
184 out
|= (SOC_DTS_CPU_MODULE0_ENABLE_BIT
|
185 SOC_DTS_CPU_MODULE1_ENABLE_BIT
);
188 out
|= SOC_DTS_AUX1_ENABLE_BIT
;
190 out
|= SOC_DTS_AUX0_ENABLE_BIT
;
191 te_out
|= int_enable_bit
;
194 out
&= ~SOC_DTS_AUX1_ENABLE_BIT
;
196 out
&= ~SOC_DTS_AUX0_ENABLE_BIT
;
197 te_out
&= ~int_enable_bit
;
199 status
= iosf_mbi_write(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_WRITE
,
200 SOC_DTS_OFFSET_PTMC
, out
);
202 goto err_restore_te_out
;
204 status
= iosf_mbi_write(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_WRITE
,
205 SOC_DTS_TE_AUX0
+ thres_index
,
208 goto err_restore_te_out
;
213 iosf_mbi_write(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_WRITE
,
214 SOC_DTS_OFFSET_PTMC
, store_te_out
);
216 iosf_mbi_write(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_WRITE
,
217 SOC_DTS_OFFSET_PTMC
, store_ptmc
);
219 iosf_mbi_write(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_WRITE
,
220 SOC_DTS_OFFSET_PTPS
, store_ptps
);
221 /* Nothing we can do if restore fails */
226 static int sys_set_trip_temp(struct thermal_zone_device
*tzd
, int trip
,
229 struct soc_sensor_entry
*aux_entry
= tzd
->devdata
;
232 if (temp
> (aux_entry
->tj_max
- crit_offset
))
235 mutex_lock(&aux_update_mutex
);
236 status
= update_trip_temp(tzd
->devdata
, trip
, temp
);
237 mutex_unlock(&aux_update_mutex
);
242 static int sys_get_trip_type(struct thermal_zone_device
*thermal
,
243 int trip
, enum thermal_trip_type
*type
)
246 *type
= THERMAL_TRIP_PASSIVE
;
248 *type
= THERMAL_TRIP_CRITICAL
;
253 static int sys_get_curr_temp(struct thermal_zone_device
*tzd
,
258 struct soc_sensor_entry
*aux_entry
;
260 aux_entry
= tzd
->devdata
;
262 status
= iosf_mbi_read(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_READ
,
263 SOC_DTS_OFFSET_TEMP
, &out
);
267 out
= (out
& aux_entry
->temp_mask
) >> aux_entry
->temp_shift
;
268 out
-= SOC_DTS_TJMAX_ENCODING
;
269 *temp
= aux_entry
->tj_max
- out
* 1000;
274 static struct thermal_zone_device_ops tzone_ops
= {
275 .get_temp
= sys_get_curr_temp
,
276 .get_trip_temp
= sys_get_trip_temp
,
277 .get_trip_type
= sys_get_trip_type
,
278 .set_trip_temp
= sys_set_trip_temp
,
281 static void free_soc_dts(struct soc_sensor_entry
*aux_entry
)
284 iosf_mbi_write(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_WRITE
,
285 SOC_DTS_OFFSET_ENABLE
, aux_entry
->store_status
);
286 thermal_zone_device_unregister(aux_entry
->tzone
);
291 static int soc_dts_enable(int id
)
296 ret
= iosf_mbi_read(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_READ
,
297 SOC_DTS_OFFSET_ENABLE
, &out
);
301 if (!(out
& BIT(id
))) {
303 ret
= iosf_mbi_write(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_WRITE
,
304 SOC_DTS_OFFSET_ENABLE
, out
);
312 static struct soc_sensor_entry
*alloc_soc_dts(int id
, u32 tj_max
,
313 bool notification_support
)
315 struct soc_sensor_entry
*aux_entry
;
321 aux_entry
= kzalloc(sizeof(*aux_entry
), GFP_KERNEL
);
324 return ERR_PTR(-ENOMEM
);
327 /* Store status to restor on exit */
328 err
= iosf_mbi_read(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_READ
,
329 SOC_DTS_OFFSET_ENABLE
,
330 &aux_entry
->store_status
);
335 aux_entry
->tj_max
= tj_max
;
336 aux_entry
->temp_mask
= 0x00FF << (id
* 8);
337 aux_entry
->temp_shift
= id
* 8;
338 if (notification_support
) {
339 trip_count
= SOC_MAX_DTS_TRIPS
;
342 snprintf(name
, sizeof(name
), "soc_dts%d", id
);
343 aux_entry
->tzone
= thermal_zone_device_register(name
,
346 aux_entry
, &tzone_ops
,
348 if (IS_ERR(aux_entry
->tzone
)) {
349 err
= PTR_ERR(aux_entry
->tzone
);
353 err
= soc_dts_enable(id
);
360 thermal_zone_device_unregister(aux_entry
->tzone
);
366 static void proc_thermal_interrupt(void)
373 spin_lock_irqsave(&intr_notify_lock
, flags
);
375 /* Clear APIC interrupt */
376 status
= iosf_mbi_read(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_READ
,
377 SOC_DTS_OFFSET_PTMC
, &ptmc_out
);
379 ptmc_out
|= SOC_DTS_PTMC_APIC_DEASSERT_BIT
;
380 status
= iosf_mbi_write(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_WRITE
,
381 SOC_DTS_OFFSET_PTMC
, ptmc_out
);
383 /* Read status here */
384 status
= iosf_mbi_read(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_READ
,
385 SOC_DTS_OFFSET_PTTSS
, &sticky_out
);
386 pr_debug("status %d PTTSS %x\n", status
, sticky_out
);
387 if (sticky_out
& SOC_DTS_TRIP_MASK
) {
389 /* reset sticky bit */
390 status
= iosf_mbi_write(BT_MBI_UNIT_PMC
, BT_MBI_BUNIT_WRITE
,
391 SOC_DTS_OFFSET_PTTSS
, sticky_out
);
392 spin_unlock_irqrestore(&intr_notify_lock
, flags
);
394 for (i
= 0; i
< SOC_MAX_DTS_SENSORS
; ++i
) {
395 pr_debug("TZD update for zone %d\n", i
);
396 thermal_zone_device_update(soc_dts
[i
]->tzone
);
399 spin_unlock_irqrestore(&intr_notify_lock
, flags
);
403 static irqreturn_t
soc_irq_thread_fn(int irq
, void *dev_data
)
405 proc_thermal_interrupt();
406 pr_debug("proc_thermal_interrupt\n");
411 static const struct x86_cpu_id soc_thermal_ids
[] = {
412 { X86_VENDOR_INTEL
, X86_FAMILY_ANY
, 0x37, 0, BYT_SOC_DTS_APIC_IRQ
},
413 { X86_VENDOR_INTEL
, X86_FAMILY_ANY
, 0x4c, 0, 0},
416 MODULE_DEVICE_TABLE(x86cpu
, soc_thermal_ids
);
418 static int __init
intel_soc_thermal_init(void)
423 const struct x86_cpu_id
*match_cpu
;
425 match_cpu
= x86_match_cpu(soc_thermal_ids
);
429 if (get_tj_max(&tj_max
))
432 soc_dts_thres_irq
= (int)match_cpu
->driver_data
;
434 for (i
= 0; i
< SOC_MAX_DTS_SENSORS
; ++i
) {
435 soc_dts
[i
] = alloc_soc_dts(i
, tj_max
,
436 soc_dts_thres_irq
? true : false);
437 if (IS_ERR(soc_dts
[i
])) {
438 err
= PTR_ERR(soc_dts
[i
]);
443 spin_lock_init(&intr_notify_lock
);
445 if (soc_dts_thres_irq
) {
446 err
= request_threaded_irq(soc_dts_thres_irq
, NULL
,
448 IRQF_TRIGGER_RISING
| IRQF_ONESHOT
,
451 pr_err("request_threaded_irq ret %d\n", err
);
456 for (i
= 0; i
< SOC_MAX_DTS_SENSORS
; ++i
) {
457 err
= update_trip_temp(soc_dts
[i
], 0, tj_max
- crit_offset
);
465 i
= SOC_MAX_DTS_SENSORS
;
466 if (soc_dts_thres_irq
)
467 free_irq(soc_dts_thres_irq
, soc_dts
);
470 free_soc_dts(soc_dts
[i
]);
475 static void __exit
intel_soc_thermal_exit(void)
479 for (i
= 0; i
< SOC_MAX_DTS_SENSORS
; ++i
)
480 update_trip_temp(soc_dts
[i
], 0, 0);
482 if (soc_dts_thres_irq
)
483 free_irq(soc_dts_thres_irq
, soc_dts
);
485 for (i
= 0; i
< SOC_MAX_DTS_SENSORS
; ++i
)
486 free_soc_dts(soc_dts
[i
]);
490 module_init(intel_soc_thermal_init
)
491 module_exit(intel_soc_thermal_exit
)
493 MODULE_DESCRIPTION("Intel SoC DTS Thermal Driver");
494 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
495 MODULE_LICENSE("GPL v2");