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