xref: /linux/drivers/thermal/intel/intel_soc_dts_iosf.c (revision 2c1ed907520c50326b8f604907a8478b27881a2e)
12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2ee073604SSrinivas Pandruvada /*
3ee073604SSrinivas Pandruvada  * intel_soc_dts_iosf.c
4ee073604SSrinivas Pandruvada  * Copyright (c) 2015, Intel Corporation.
5ee073604SSrinivas Pandruvada  */
6ee073604SSrinivas Pandruvada 
7ee073604SSrinivas Pandruvada #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8ee073604SSrinivas Pandruvada 
99f00ebf5SWilliam Breathitt Gray #include <linux/bitops.h>
10955fb871SZhang Rui #include <linux/intel_tcc.h>
11ee073604SSrinivas Pandruvada #include <linux/module.h>
12ee073604SSrinivas Pandruvada #include <linux/slab.h>
13ee073604SSrinivas Pandruvada #include <linux/interrupt.h>
14ee073604SSrinivas Pandruvada #include <asm/iosf_mbi.h>
15ee073604SSrinivas Pandruvada #include "intel_soc_dts_iosf.h"
16ee073604SSrinivas Pandruvada 
17ee073604SSrinivas Pandruvada #define SOC_DTS_OFFSET_ENABLE		0xB0
18ee073604SSrinivas Pandruvada #define SOC_DTS_OFFSET_TEMP		0xB1
19ee073604SSrinivas Pandruvada 
20ee073604SSrinivas Pandruvada #define SOC_DTS_OFFSET_PTPS		0xB2
21ee073604SSrinivas Pandruvada #define SOC_DTS_OFFSET_PTTS		0xB3
22ee073604SSrinivas Pandruvada #define SOC_DTS_OFFSET_PTTSS		0xB4
23ee073604SSrinivas Pandruvada #define SOC_DTS_OFFSET_PTMC		0x80
24ee073604SSrinivas Pandruvada #define SOC_DTS_TE_AUX0			0xB5
25ee073604SSrinivas Pandruvada #define SOC_DTS_TE_AUX1			0xB6
26ee073604SSrinivas Pandruvada 
27ee073604SSrinivas Pandruvada #define SOC_DTS_AUX0_ENABLE_BIT		BIT(0)
28ee073604SSrinivas Pandruvada #define SOC_DTS_AUX1_ENABLE_BIT		BIT(1)
29ee073604SSrinivas Pandruvada #define SOC_DTS_CPU_MODULE0_ENABLE_BIT	BIT(16)
30ee073604SSrinivas Pandruvada #define SOC_DTS_CPU_MODULE1_ENABLE_BIT	BIT(17)
31ee073604SSrinivas Pandruvada #define SOC_DTS_TE_SCI_ENABLE		BIT(9)
32ee073604SSrinivas Pandruvada #define SOC_DTS_TE_SMI_ENABLE		BIT(10)
33ee073604SSrinivas Pandruvada #define SOC_DTS_TE_MSI_ENABLE		BIT(11)
34ee073604SSrinivas Pandruvada #define SOC_DTS_TE_APICA_ENABLE		BIT(14)
35ee073604SSrinivas Pandruvada #define SOC_DTS_PTMC_APIC_DEASSERT_BIT	BIT(4)
36ee073604SSrinivas Pandruvada 
37ee073604SSrinivas Pandruvada /* DTS encoding for TJ MAX temperature */
38ee073604SSrinivas Pandruvada #define SOC_DTS_TJMAX_ENCODING		0x7F
39ee073604SSrinivas Pandruvada 
40ee073604SSrinivas Pandruvada /* Mask for two trips in status bits */
41ee073604SSrinivas Pandruvada #define SOC_DTS_TRIP_MASK		0x03
42ee073604SSrinivas Pandruvada 
update_trip_temp(struct intel_soc_dts_sensors * sensors,int thres_index,int temp)43cbc28057SRafael J. Wysocki static int update_trip_temp(struct intel_soc_dts_sensors *sensors,
440b28ba27SRafael J. Wysocki 			    int thres_index, int temp)
45ee073604SSrinivas Pandruvada {
46ee073604SSrinivas Pandruvada 	int status;
47ee073604SSrinivas Pandruvada 	u32 temp_out;
48ee073604SSrinivas Pandruvada 	u32 out;
499f00ebf5SWilliam Breathitt Gray 	unsigned long update_ptps;
50ee073604SSrinivas Pandruvada 	u32 store_ptps;
51ee073604SSrinivas Pandruvada 	u32 store_ptmc;
52ee073604SSrinivas Pandruvada 	u32 store_te_out;
53ee073604SSrinivas Pandruvada 	u32 te_out;
54ee073604SSrinivas Pandruvada 	u32 int_enable_bit = SOC_DTS_TE_APICA_ENABLE;
55ee073604SSrinivas Pandruvada 
56ee073604SSrinivas Pandruvada 	if (sensors->intr_type == INTEL_SOC_DTS_INTERRUPT_MSI)
57ee073604SSrinivas Pandruvada 		int_enable_bit |= SOC_DTS_TE_MSI_ENABLE;
58ee073604SSrinivas Pandruvada 
59ee073604SSrinivas Pandruvada 	temp_out = (sensors->tj_max - temp) / 1000;
60ee073604SSrinivas Pandruvada 
614077a387SAndy Shevchenko 	status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
62ee073604SSrinivas Pandruvada 			       SOC_DTS_OFFSET_PTPS, &store_ptps);
63ee073604SSrinivas Pandruvada 	if (status)
64ee073604SSrinivas Pandruvada 		return status;
65ee073604SSrinivas Pandruvada 
669f00ebf5SWilliam Breathitt Gray 	update_ptps = store_ptps;
679f00ebf5SWilliam Breathitt Gray 	bitmap_set_value8(&update_ptps, temp_out & 0xFF, thres_index * 8);
689f00ebf5SWilliam Breathitt Gray 	out = update_ptps;
699f00ebf5SWilliam Breathitt Gray 
704077a387SAndy Shevchenko 	status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
71ee073604SSrinivas Pandruvada 				SOC_DTS_OFFSET_PTPS, out);
72ee073604SSrinivas Pandruvada 	if (status)
73ee073604SSrinivas Pandruvada 		return status;
74ee073604SSrinivas Pandruvada 
75ee073604SSrinivas Pandruvada 	pr_debug("update_trip_temp PTPS = %x\n", out);
764077a387SAndy Shevchenko 	status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
77ee073604SSrinivas Pandruvada 			       SOC_DTS_OFFSET_PTMC, &out);
78ee073604SSrinivas Pandruvada 	if (status)
79ee073604SSrinivas Pandruvada 		goto err_restore_ptps;
80ee073604SSrinivas Pandruvada 
81ee073604SSrinivas Pandruvada 	store_ptmc = out;
82ee073604SSrinivas Pandruvada 
834077a387SAndy Shevchenko 	status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
84ee073604SSrinivas Pandruvada 			       SOC_DTS_TE_AUX0 + thres_index,
85ee073604SSrinivas Pandruvada 			       &te_out);
86ee073604SSrinivas Pandruvada 	if (status)
87ee073604SSrinivas Pandruvada 		goto err_restore_ptmc;
88ee073604SSrinivas Pandruvada 
89ee073604SSrinivas Pandruvada 	store_te_out = te_out;
90ee073604SSrinivas Pandruvada 	/* Enable for CPU module 0 and module 1 */
91ee073604SSrinivas Pandruvada 	out |= (SOC_DTS_CPU_MODULE0_ENABLE_BIT |
92ee073604SSrinivas Pandruvada 					SOC_DTS_CPU_MODULE1_ENABLE_BIT);
93ee073604SSrinivas Pandruvada 	if (temp) {
94ee073604SSrinivas Pandruvada 		if (thres_index)
95ee073604SSrinivas Pandruvada 			out |= SOC_DTS_AUX1_ENABLE_BIT;
96ee073604SSrinivas Pandruvada 		else
97ee073604SSrinivas Pandruvada 			out |= SOC_DTS_AUX0_ENABLE_BIT;
98ee073604SSrinivas Pandruvada 		te_out |= int_enable_bit;
99ee073604SSrinivas Pandruvada 	} else {
100ee073604SSrinivas Pandruvada 		if (thres_index)
101ee073604SSrinivas Pandruvada 			out &= ~SOC_DTS_AUX1_ENABLE_BIT;
102ee073604SSrinivas Pandruvada 		else
103ee073604SSrinivas Pandruvada 			out &= ~SOC_DTS_AUX0_ENABLE_BIT;
104ee073604SSrinivas Pandruvada 		te_out &= ~int_enable_bit;
105ee073604SSrinivas Pandruvada 	}
1064077a387SAndy Shevchenko 	status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
107ee073604SSrinivas Pandruvada 				SOC_DTS_OFFSET_PTMC, out);
108ee073604SSrinivas Pandruvada 	if (status)
109ee073604SSrinivas Pandruvada 		goto err_restore_te_out;
110ee073604SSrinivas Pandruvada 
1114077a387SAndy Shevchenko 	status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
112ee073604SSrinivas Pandruvada 				SOC_DTS_TE_AUX0 + thres_index,
113ee073604SSrinivas Pandruvada 				te_out);
114ee073604SSrinivas Pandruvada 	if (status)
115ee073604SSrinivas Pandruvada 		goto err_restore_te_out;
116ee073604SSrinivas Pandruvada 
117ee073604SSrinivas Pandruvada 	return 0;
118ee073604SSrinivas Pandruvada err_restore_te_out:
1194077a387SAndy Shevchenko 	iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
120ee073604SSrinivas Pandruvada 		       SOC_DTS_OFFSET_PTMC, store_te_out);
121ee073604SSrinivas Pandruvada err_restore_ptmc:
1224077a387SAndy Shevchenko 	iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
123ee073604SSrinivas Pandruvada 		       SOC_DTS_OFFSET_PTMC, store_ptmc);
124ee073604SSrinivas Pandruvada err_restore_ptps:
1254077a387SAndy Shevchenko 	iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
126ee073604SSrinivas Pandruvada 		       SOC_DTS_OFFSET_PTPS, store_ptps);
127ee073604SSrinivas Pandruvada 	/* Nothing we can do if restore fails */
128ee073604SSrinivas Pandruvada 
129ee073604SSrinivas Pandruvada 	return status;
130ee073604SSrinivas Pandruvada }
131ee073604SSrinivas Pandruvada 
sys_set_trip_temp(struct thermal_zone_device * tzd,const struct thermal_trip * trip,int temp)1320728c810SRafael J. Wysocki static int sys_set_trip_temp(struct thermal_zone_device *tzd,
1330728c810SRafael J. Wysocki 			     const struct thermal_trip *trip,
13417e8351aSSascha Hauer 			     int temp)
135ee073604SSrinivas Pandruvada {
1365f68d078SDaniel Lezcano 	struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_priv(tzd);
137ee073604SSrinivas Pandruvada 	struct intel_soc_dts_sensors *sensors = dts->sensors;
1380728c810SRafael J. Wysocki 	unsigned int trip_index = THERMAL_TRIP_PRIV_TO_INT(trip->priv);
139ee073604SSrinivas Pandruvada 	int status;
140ee073604SSrinivas Pandruvada 
141ee073604SSrinivas Pandruvada 	if (temp > sensors->tj_max)
142ee073604SSrinivas Pandruvada 		return -EINVAL;
143ee073604SSrinivas Pandruvada 
144ee073604SSrinivas Pandruvada 	mutex_lock(&sensors->dts_update_lock);
1450728c810SRafael J. Wysocki 	status = update_trip_temp(sensors, trip_index, temp);
146ee073604SSrinivas Pandruvada 	mutex_unlock(&sensors->dts_update_lock);
147ee073604SSrinivas Pandruvada 
148ee073604SSrinivas Pandruvada 	return status;
149ee073604SSrinivas Pandruvada }
150ee073604SSrinivas Pandruvada 
sys_get_curr_temp(struct thermal_zone_device * tzd,int * temp)151ee073604SSrinivas Pandruvada static int sys_get_curr_temp(struct thermal_zone_device *tzd,
15217e8351aSSascha Hauer 			     int *temp)
153ee073604SSrinivas Pandruvada {
154ee073604SSrinivas Pandruvada 	int status;
155ee073604SSrinivas Pandruvada 	u32 out;
1565f68d078SDaniel Lezcano 	struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_priv(tzd);
157ee073604SSrinivas Pandruvada 	struct intel_soc_dts_sensors *sensors;
1589f00ebf5SWilliam Breathitt Gray 	unsigned long raw;
159ee073604SSrinivas Pandruvada 
160ee073604SSrinivas Pandruvada 	sensors = dts->sensors;
1614077a387SAndy Shevchenko 	status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
162ee073604SSrinivas Pandruvada 			       SOC_DTS_OFFSET_TEMP, &out);
163ee073604SSrinivas Pandruvada 	if (status)
164ee073604SSrinivas Pandruvada 		return status;
165ee073604SSrinivas Pandruvada 
1669f00ebf5SWilliam Breathitt Gray 	raw = out;
1679f00ebf5SWilliam Breathitt Gray 	out = bitmap_get_value8(&raw, dts->id * 8) - SOC_DTS_TJMAX_ENCODING;
168ee073604SSrinivas Pandruvada 	*temp = sensors->tj_max - out * 1000;
169ee073604SSrinivas Pandruvada 
170ee073604SSrinivas Pandruvada 	return 0;
171ee073604SSrinivas Pandruvada }
172ee073604SSrinivas Pandruvada 
17362dd1784SRafael J. Wysocki static const struct thermal_zone_device_ops tzone_ops = {
174ee073604SSrinivas Pandruvada 	.get_temp = sys_get_curr_temp,
175ee073604SSrinivas Pandruvada 	.set_trip_temp = sys_set_trip_temp,
176ee073604SSrinivas Pandruvada };
177ee073604SSrinivas Pandruvada 
soc_dts_enable(int id)178ee073604SSrinivas Pandruvada static int soc_dts_enable(int id)
179ee073604SSrinivas Pandruvada {
180ee073604SSrinivas Pandruvada 	u32 out;
181ee073604SSrinivas Pandruvada 	int ret;
182ee073604SSrinivas Pandruvada 
1834077a387SAndy Shevchenko 	ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
184ee073604SSrinivas Pandruvada 			    SOC_DTS_OFFSET_ENABLE, &out);
185ee073604SSrinivas Pandruvada 	if (ret)
186ee073604SSrinivas Pandruvada 		return ret;
187ee073604SSrinivas Pandruvada 
188ee073604SSrinivas Pandruvada 	if (!(out & BIT(id))) {
189ee073604SSrinivas Pandruvada 		out |= BIT(id);
1904077a387SAndy Shevchenko 		ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
191ee073604SSrinivas Pandruvada 				     SOC_DTS_OFFSET_ENABLE, out);
192ee073604SSrinivas Pandruvada 		if (ret)
193ee073604SSrinivas Pandruvada 			return ret;
194ee073604SSrinivas Pandruvada 	}
195ee073604SSrinivas Pandruvada 
196ee073604SSrinivas Pandruvada 	return ret;
197ee073604SSrinivas Pandruvada }
198ee073604SSrinivas Pandruvada 
remove_dts_thermal_zone(struct intel_soc_dts_sensor_entry * dts)199ee073604SSrinivas Pandruvada static void remove_dts_thermal_zone(struct intel_soc_dts_sensor_entry *dts)
200ee073604SSrinivas Pandruvada {
2014077a387SAndy Shevchenko 	iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
202ee073604SSrinivas Pandruvada 		       SOC_DTS_OFFSET_ENABLE, dts->store_status);
203ee073604SSrinivas Pandruvada 	thermal_zone_device_unregister(dts->tzone);
204ee073604SSrinivas Pandruvada }
205ee073604SSrinivas Pandruvada 
add_dts_thermal_zone(int id,struct intel_soc_dts_sensor_entry * dts,struct thermal_trip * trips)206ee073604SSrinivas Pandruvada static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts,
207cca52f69SRafael J. Wysocki 				struct thermal_trip *trips)
208ee073604SSrinivas Pandruvada {
209ee073604SSrinivas Pandruvada 	char name[10];
210ee073604SSrinivas Pandruvada 	u32 store_ptps;
211ee073604SSrinivas Pandruvada 	int ret;
212ee073604SSrinivas Pandruvada 
213ee073604SSrinivas Pandruvada 	/* Store status to restor on exit */
2144077a387SAndy Shevchenko 	ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
2154077a387SAndy Shevchenko 			    SOC_DTS_OFFSET_ENABLE, &dts->store_status);
216ee073604SSrinivas Pandruvada 	if (ret)
217ee073604SSrinivas Pandruvada 		goto err_ret;
218ee073604SSrinivas Pandruvada 
219ee073604SSrinivas Pandruvada 	dts->id = id;
2204f164435SRafael J. Wysocki 
221ee073604SSrinivas Pandruvada 	/* Check if the writable trip we provide is not used by BIOS */
2224077a387SAndy Shevchenko 	ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
223ee073604SSrinivas Pandruvada 			    SOC_DTS_OFFSET_PTPS, &store_ptps);
224cca52f69SRafael J. Wysocki 	if (!ret) {
225cca52f69SRafael J. Wysocki 		int i;
226cca52f69SRafael J. Wysocki 
227cca52f69SRafael J. Wysocki 		for (i = 0; i <= 1; i++) {
228cca52f69SRafael J. Wysocki 			if (store_ptps & (0xFFU << i * 8))
229cca52f69SRafael J. Wysocki 				trips[i].flags &= ~THERMAL_TRIP_FLAG_RW_TEMP;
230ee073604SSrinivas Pandruvada 		}
231cca52f69SRafael J. Wysocki 	}
232ee073604SSrinivas Pandruvada 	snprintf(name, sizeof(name), "soc_dts%d", id);
233fcbf8780SRafael J. Wysocki 	dts->tzone = thermal_zone_device_register_with_trips(name, trips,
234b429b6ffSRafael J. Wysocki 							     SOC_MAX_DTS_TRIPS,
2354a62d588SRafael J. Wysocki 							     dts, &tzone_ops,
236ee073604SSrinivas Pandruvada 							     NULL, 0, 0);
237ee073604SSrinivas Pandruvada 	if (IS_ERR(dts->tzone)) {
238ee073604SSrinivas Pandruvada 		ret = PTR_ERR(dts->tzone);
239ee073604SSrinivas Pandruvada 		goto err_ret;
240ee073604SSrinivas Pandruvada 	}
241bbcf90c0SAndrzej Pietrasiewicz 	ret = thermal_zone_device_enable(dts->tzone);
242bbcf90c0SAndrzej Pietrasiewicz 	if (ret)
243bbcf90c0SAndrzej Pietrasiewicz 		goto err_enable;
244ee073604SSrinivas Pandruvada 
245ee073604SSrinivas Pandruvada 	ret = soc_dts_enable(id);
246ee073604SSrinivas Pandruvada 	if (ret)
247ee073604SSrinivas Pandruvada 		goto err_enable;
248ee073604SSrinivas Pandruvada 
249ee073604SSrinivas Pandruvada 	return 0;
250ee073604SSrinivas Pandruvada err_enable:
251ee073604SSrinivas Pandruvada 	thermal_zone_device_unregister(dts->tzone);
252ee073604SSrinivas Pandruvada err_ret:
253ee073604SSrinivas Pandruvada 	return ret;
254ee073604SSrinivas Pandruvada }
255ee073604SSrinivas Pandruvada 
intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors * sensors)256ee073604SSrinivas Pandruvada void intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors *sensors)
257ee073604SSrinivas Pandruvada {
258ee073604SSrinivas Pandruvada 	u32 sticky_out;
259ee073604SSrinivas Pandruvada 	int status;
260ee073604SSrinivas Pandruvada 	u32 ptmc_out;
261ee073604SSrinivas Pandruvada 	unsigned long flags;
262ee073604SSrinivas Pandruvada 
263ee073604SSrinivas Pandruvada 	spin_lock_irqsave(&sensors->intr_notify_lock, flags);
264ee073604SSrinivas Pandruvada 
2654077a387SAndy Shevchenko 	status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
266ee073604SSrinivas Pandruvada 			       SOC_DTS_OFFSET_PTMC, &ptmc_out);
267ee073604SSrinivas Pandruvada 	ptmc_out |= SOC_DTS_PTMC_APIC_DEASSERT_BIT;
2684077a387SAndy Shevchenko 	status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
269ee073604SSrinivas Pandruvada 				SOC_DTS_OFFSET_PTMC, ptmc_out);
270ee073604SSrinivas Pandruvada 
2714077a387SAndy Shevchenko 	status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
272ee073604SSrinivas Pandruvada 			       SOC_DTS_OFFSET_PTTSS, &sticky_out);
273ee073604SSrinivas Pandruvada 	pr_debug("status %d PTTSS %x\n", status, sticky_out);
274ee073604SSrinivas Pandruvada 	if (sticky_out & SOC_DTS_TRIP_MASK) {
275ee073604SSrinivas Pandruvada 		int i;
276ee073604SSrinivas Pandruvada 		/* reset sticky bit */
2774077a387SAndy Shevchenko 		status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
278ee073604SSrinivas Pandruvada 					SOC_DTS_OFFSET_PTTSS, sticky_out);
279ee073604SSrinivas Pandruvada 		spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
280ee073604SSrinivas Pandruvada 
281ee073604SSrinivas Pandruvada 		for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
282ee073604SSrinivas Pandruvada 			pr_debug("TZD update for zone %d\n", i);
2830e70f466SSrinivas Pandruvada 			thermal_zone_device_update(sensors->soc_dts[i].tzone,
2840e70f466SSrinivas Pandruvada 						   THERMAL_EVENT_UNSPECIFIED);
285ee073604SSrinivas Pandruvada 		}
286ee073604SSrinivas Pandruvada 	} else
287ee073604SSrinivas Pandruvada 		spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
288ee073604SSrinivas Pandruvada }
289ee073604SSrinivas Pandruvada EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_interrupt_handler);
290ee073604SSrinivas Pandruvada 
dts_trips_reset(struct intel_soc_dts_sensors * sensors,int dts_index)2915bc3da35SRafael J. Wysocki static void dts_trips_reset(struct intel_soc_dts_sensors *sensors, int dts_index)
2925bc3da35SRafael J. Wysocki {
293fcbf8780SRafael J. Wysocki 	update_trip_temp(sensors, 0, 0);
294fcbf8780SRafael J. Wysocki 	update_trip_temp(sensors, 1, 0);
2955bc3da35SRafael J. Wysocki }
2965bc3da35SRafael J. Wysocki 
set_trip(struct thermal_trip * trip,enum thermal_trip_type type,u8 flags,int temp,unsigned int index)297cca52f69SRafael J. Wysocki static void set_trip(struct thermal_trip *trip, enum thermal_trip_type type,
2980728c810SRafael J. Wysocki 		     u8 flags, int temp, unsigned int index)
299cca52f69SRafael J. Wysocki {
300cca52f69SRafael J. Wysocki 	trip->type = type;
301cca52f69SRafael J. Wysocki 	trip->flags = flags;
302cca52f69SRafael J. Wysocki 	trip->temperature = temp;
3030728c810SRafael J. Wysocki 	trip->priv = THERMAL_INT_TO_TRIP_PRIV(index);
304cca52f69SRafael J. Wysocki }
305cca52f69SRafael J. Wysocki 
30602a49aacSRafael J. Wysocki struct intel_soc_dts_sensors *
intel_soc_dts_iosf_init(enum intel_soc_dts_interrupt_type intr_type,bool critical_trip,int crit_offset)30702a49aacSRafael J. Wysocki intel_soc_dts_iosf_init(enum intel_soc_dts_interrupt_type intr_type,
30802a49aacSRafael J. Wysocki 			bool critical_trip, int crit_offset)
309ee073604SSrinivas Pandruvada {
310fcbf8780SRafael J. Wysocki 	struct thermal_trip trips[SOC_MAX_DTS_SENSORS][SOC_MAX_DTS_TRIPS] = { 0 };
311ee073604SSrinivas Pandruvada 	struct intel_soc_dts_sensors *sensors;
312e7fcfe67SYang Li 	int tj_max;
313ee073604SSrinivas Pandruvada 	int ret;
314ee073604SSrinivas Pandruvada 	int i;
315ee073604SSrinivas Pandruvada 
316ee073604SSrinivas Pandruvada 	if (!iosf_mbi_available())
317ee073604SSrinivas Pandruvada 		return ERR_PTR(-ENODEV);
318ee073604SSrinivas Pandruvada 
319955fb871SZhang Rui 	tj_max = intel_tcc_get_tjmax(-1);
320955fb871SZhang Rui 	if (tj_max < 0)
321955fb871SZhang Rui 		return ERR_PTR(tj_max);
322ee073604SSrinivas Pandruvada 
323ee073604SSrinivas Pandruvada 	sensors = kzalloc(sizeof(*sensors), GFP_KERNEL);
324ee073604SSrinivas Pandruvada 	if (!sensors)
325ee073604SSrinivas Pandruvada 		return ERR_PTR(-ENOMEM);
326ee073604SSrinivas Pandruvada 
327ee073604SSrinivas Pandruvada 	spin_lock_init(&sensors->intr_notify_lock);
328ee073604SSrinivas Pandruvada 	mutex_init(&sensors->dts_update_lock);
329ee073604SSrinivas Pandruvada 	sensors->intr_type = intr_type;
3300bb619f9SHans de Goede 	sensors->tj_max = tj_max * 1000;
3314f164435SRafael J. Wysocki 
332ee073604SSrinivas Pandruvada 	for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
33302a49aacSRafael J. Wysocki 		int temp;
33402a49aacSRafael J. Wysocki 
335ee073604SSrinivas Pandruvada 		sensors->soc_dts[i].sensors = sensors;
336ee073604SSrinivas Pandruvada 
337cca52f69SRafael J. Wysocki 		set_trip(&trips[i][0], THERMAL_TRIP_PASSIVE,
3380728c810SRafael J. Wysocki 			 THERMAL_TRIP_FLAG_RW_TEMP, 0, 0);
339cca52f69SRafael J. Wysocki 
340fcbf8780SRafael J. Wysocki 		ret = update_trip_temp(sensors, 0, 0);
341ee073604SSrinivas Pandruvada 		if (ret)
34251f2aaf0SRafael J. Wysocki 			goto err_reset_trips;
343ee073604SSrinivas Pandruvada 
34402a49aacSRafael J. Wysocki 		if (critical_trip) {
34502a49aacSRafael J. Wysocki 			temp = sensors->tj_max - crit_offset;
3460728c810SRafael J. Wysocki 			set_trip(&trips[i][1], THERMAL_TRIP_CRITICAL, 0, temp, 1);
34702a49aacSRafael J. Wysocki 		} else {
348cca52f69SRafael J. Wysocki 			set_trip(&trips[i][1], THERMAL_TRIP_PASSIVE,
3490728c810SRafael J. Wysocki 				 THERMAL_TRIP_FLAG_RW_TEMP, 0, 1);
35002a49aacSRafael J. Wysocki 			temp = 0;
35102a49aacSRafael J. Wysocki 		}
352cca52f69SRafael J. Wysocki 
353fcbf8780SRafael J. Wysocki 		ret = update_trip_temp(sensors, 1, temp);
354ee073604SSrinivas Pandruvada 		if (ret)
35551f2aaf0SRafael J. Wysocki 			goto err_reset_trips;
35651f2aaf0SRafael J. Wysocki 	}
35751f2aaf0SRafael J. Wysocki 
35851f2aaf0SRafael J. Wysocki 	for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
359cca52f69SRafael J. Wysocki 		ret = add_dts_thermal_zone(i, &sensors->soc_dts[i], trips[i]);
36051f2aaf0SRafael J. Wysocki 		if (ret)
361ee073604SSrinivas Pandruvada 			goto err_remove_zone;
362ee073604SSrinivas Pandruvada 	}
363ee073604SSrinivas Pandruvada 
364ee073604SSrinivas Pandruvada 	return sensors;
36551f2aaf0SRafael J. Wysocki 
366ee073604SSrinivas Pandruvada err_remove_zone:
367ee073604SSrinivas Pandruvada 	for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i)
368ee073604SSrinivas Pandruvada 		remove_dts_thermal_zone(&sensors->soc_dts[i]);
369ee073604SSrinivas Pandruvada 
37051f2aaf0SRafael J. Wysocki err_reset_trips:
3715bc3da35SRafael J. Wysocki 	for (i = 0; i < SOC_MAX_DTS_SENSORS; i++)
3725bc3da35SRafael J. Wysocki 		dts_trips_reset(sensors, i);
37351f2aaf0SRafael J. Wysocki 
374ee073604SSrinivas Pandruvada 	kfree(sensors);
375ee073604SSrinivas Pandruvada 	return ERR_PTR(ret);
376ee073604SSrinivas Pandruvada }
377ee073604SSrinivas Pandruvada EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_init);
378ee073604SSrinivas Pandruvada 
intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors * sensors)379ee073604SSrinivas Pandruvada void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors)
380ee073604SSrinivas Pandruvada {
381ee073604SSrinivas Pandruvada 	int i;
382ee073604SSrinivas Pandruvada 
383ee073604SSrinivas Pandruvada 	for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
38451f2aaf0SRafael J. Wysocki 		remove_dts_thermal_zone(&sensors->soc_dts[i]);
3855bc3da35SRafael J. Wysocki 		dts_trips_reset(sensors, i);
386ee073604SSrinivas Pandruvada 	}
387ee073604SSrinivas Pandruvada 	kfree(sensors);
388ee073604SSrinivas Pandruvada }
389ee073604SSrinivas Pandruvada EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_exit);
390ee073604SSrinivas Pandruvada 
391*cdd30ebbSPeter Zijlstra MODULE_IMPORT_NS("INTEL_TCC");
392ee073604SSrinivas Pandruvada MODULE_LICENSE("GPL v2");
39348d722fdSSrinivas Pandruvada MODULE_DESCRIPTION("SoC DTS driver using side band interface");
394