12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
23e8c4d31SAmit Kucheria /*
33e8c4d31SAmit Kucheria * intel_soc_dts_iosf.c
43e8c4d31SAmit Kucheria * Copyright (c) 2015, Intel Corporation.
53e8c4d31SAmit Kucheria */
63e8c4d31SAmit Kucheria
73e8c4d31SAmit Kucheria #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
83e8c4d31SAmit Kucheria
99f00ebf5SWilliam Breathitt Gray #include <linux/bitops.h>
10955fb871SZhang Rui #include <linux/intel_tcc.h>
113e8c4d31SAmit Kucheria #include <linux/module.h>
123e8c4d31SAmit Kucheria #include <linux/slab.h>
133e8c4d31SAmit Kucheria #include <linux/interrupt.h>
143e8c4d31SAmit Kucheria #include <asm/iosf_mbi.h>
153e8c4d31SAmit Kucheria #include "intel_soc_dts_iosf.h"
163e8c4d31SAmit Kucheria
173e8c4d31SAmit Kucheria #define SOC_DTS_OFFSET_ENABLE 0xB0
183e8c4d31SAmit Kucheria #define SOC_DTS_OFFSET_TEMP 0xB1
193e8c4d31SAmit Kucheria
203e8c4d31SAmit Kucheria #define SOC_DTS_OFFSET_PTPS 0xB2
213e8c4d31SAmit Kucheria #define SOC_DTS_OFFSET_PTTS 0xB3
223e8c4d31SAmit Kucheria #define SOC_DTS_OFFSET_PTTSS 0xB4
233e8c4d31SAmit Kucheria #define SOC_DTS_OFFSET_PTMC 0x80
243e8c4d31SAmit Kucheria #define SOC_DTS_TE_AUX0 0xB5
253e8c4d31SAmit Kucheria #define SOC_DTS_TE_AUX1 0xB6
263e8c4d31SAmit Kucheria
273e8c4d31SAmit Kucheria #define SOC_DTS_AUX0_ENABLE_BIT BIT(0)
283e8c4d31SAmit Kucheria #define SOC_DTS_AUX1_ENABLE_BIT BIT(1)
293e8c4d31SAmit Kucheria #define SOC_DTS_CPU_MODULE0_ENABLE_BIT BIT(16)
303e8c4d31SAmit Kucheria #define SOC_DTS_CPU_MODULE1_ENABLE_BIT BIT(17)
313e8c4d31SAmit Kucheria #define SOC_DTS_TE_SCI_ENABLE BIT(9)
323e8c4d31SAmit Kucheria #define SOC_DTS_TE_SMI_ENABLE BIT(10)
333e8c4d31SAmit Kucheria #define SOC_DTS_TE_MSI_ENABLE BIT(11)
343e8c4d31SAmit Kucheria #define SOC_DTS_TE_APICA_ENABLE BIT(14)
353e8c4d31SAmit Kucheria #define SOC_DTS_PTMC_APIC_DEASSERT_BIT BIT(4)
363e8c4d31SAmit Kucheria
373e8c4d31SAmit Kucheria /* DTS encoding for TJ MAX temperature */
383e8c4d31SAmit Kucheria #define SOC_DTS_TJMAX_ENCODING 0x7F
393e8c4d31SAmit Kucheria
403e8c4d31SAmit Kucheria /* Mask for two trips in status bits */
413e8c4d31SAmit Kucheria #define SOC_DTS_TRIP_MASK 0x03
423e8c4d31SAmit Kucheria
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)
453e8c4d31SAmit Kucheria {
463e8c4d31SAmit Kucheria int status;
473e8c4d31SAmit Kucheria u32 temp_out;
483e8c4d31SAmit Kucheria u32 out;
499f00ebf5SWilliam Breathitt Gray unsigned long update_ptps;
503e8c4d31SAmit Kucheria u32 store_ptps;
513e8c4d31SAmit Kucheria u32 store_ptmc;
523e8c4d31SAmit Kucheria u32 store_te_out;
533e8c4d31SAmit Kucheria u32 te_out;
543e8c4d31SAmit Kucheria u32 int_enable_bit = SOC_DTS_TE_APICA_ENABLE;
553e8c4d31SAmit Kucheria
563e8c4d31SAmit Kucheria if (sensors->intr_type == INTEL_SOC_DTS_INTERRUPT_MSI)
573e8c4d31SAmit Kucheria int_enable_bit |= SOC_DTS_TE_MSI_ENABLE;
583e8c4d31SAmit Kucheria
593e8c4d31SAmit Kucheria temp_out = (sensors->tj_max - temp) / 1000;
603e8c4d31SAmit Kucheria
613e8c4d31SAmit Kucheria status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
623e8c4d31SAmit Kucheria SOC_DTS_OFFSET_PTPS, &store_ptps);
633e8c4d31SAmit Kucheria if (status)
643e8c4d31SAmit Kucheria return status;
653e8c4d31SAmit Kucheria
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
703e8c4d31SAmit Kucheria status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
713e8c4d31SAmit Kucheria SOC_DTS_OFFSET_PTPS, out);
723e8c4d31SAmit Kucheria if (status)
733e8c4d31SAmit Kucheria return status;
743e8c4d31SAmit Kucheria
753e8c4d31SAmit Kucheria pr_debug("update_trip_temp PTPS = %x\n", out);
763e8c4d31SAmit Kucheria status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
773e8c4d31SAmit Kucheria SOC_DTS_OFFSET_PTMC, &out);
783e8c4d31SAmit Kucheria if (status)
793e8c4d31SAmit Kucheria goto err_restore_ptps;
803e8c4d31SAmit Kucheria
813e8c4d31SAmit Kucheria store_ptmc = out;
823e8c4d31SAmit Kucheria
833e8c4d31SAmit Kucheria status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
843e8c4d31SAmit Kucheria SOC_DTS_TE_AUX0 + thres_index,
853e8c4d31SAmit Kucheria &te_out);
863e8c4d31SAmit Kucheria if (status)
873e8c4d31SAmit Kucheria goto err_restore_ptmc;
883e8c4d31SAmit Kucheria
893e8c4d31SAmit Kucheria store_te_out = te_out;
903e8c4d31SAmit Kucheria /* Enable for CPU module 0 and module 1 */
913e8c4d31SAmit Kucheria out |= (SOC_DTS_CPU_MODULE0_ENABLE_BIT |
923e8c4d31SAmit Kucheria SOC_DTS_CPU_MODULE1_ENABLE_BIT);
933e8c4d31SAmit Kucheria if (temp) {
943e8c4d31SAmit Kucheria if (thres_index)
953e8c4d31SAmit Kucheria out |= SOC_DTS_AUX1_ENABLE_BIT;
963e8c4d31SAmit Kucheria else
973e8c4d31SAmit Kucheria out |= SOC_DTS_AUX0_ENABLE_BIT;
983e8c4d31SAmit Kucheria te_out |= int_enable_bit;
993e8c4d31SAmit Kucheria } else {
1003e8c4d31SAmit Kucheria if (thres_index)
1013e8c4d31SAmit Kucheria out &= ~SOC_DTS_AUX1_ENABLE_BIT;
1023e8c4d31SAmit Kucheria else
1033e8c4d31SAmit Kucheria out &= ~SOC_DTS_AUX0_ENABLE_BIT;
1043e8c4d31SAmit Kucheria te_out &= ~int_enable_bit;
1053e8c4d31SAmit Kucheria }
1063e8c4d31SAmit Kucheria status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
1073e8c4d31SAmit Kucheria SOC_DTS_OFFSET_PTMC, out);
1083e8c4d31SAmit Kucheria if (status)
1093e8c4d31SAmit Kucheria goto err_restore_te_out;
1103e8c4d31SAmit Kucheria
1113e8c4d31SAmit Kucheria status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
1123e8c4d31SAmit Kucheria SOC_DTS_TE_AUX0 + thres_index,
1133e8c4d31SAmit Kucheria te_out);
1143e8c4d31SAmit Kucheria if (status)
1153e8c4d31SAmit Kucheria goto err_restore_te_out;
1163e8c4d31SAmit Kucheria
1173e8c4d31SAmit Kucheria return 0;
1183e8c4d31SAmit Kucheria err_restore_te_out:
1193e8c4d31SAmit Kucheria iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
1203e8c4d31SAmit Kucheria SOC_DTS_OFFSET_PTMC, store_te_out);
1213e8c4d31SAmit Kucheria err_restore_ptmc:
1223e8c4d31SAmit Kucheria iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
1233e8c4d31SAmit Kucheria SOC_DTS_OFFSET_PTMC, store_ptmc);
1243e8c4d31SAmit Kucheria err_restore_ptps:
1253e8c4d31SAmit Kucheria iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
1263e8c4d31SAmit Kucheria SOC_DTS_OFFSET_PTPS, store_ptps);
1273e8c4d31SAmit Kucheria /* Nothing we can do if restore fails */
1283e8c4d31SAmit Kucheria
1293e8c4d31SAmit Kucheria return status;
1303e8c4d31SAmit Kucheria }
1313e8c4d31SAmit Kucheria
configure_trip(struct intel_soc_dts_sensor_entry * dts,int thres_index,enum thermal_trip_type trip_type,int temp)1320b28ba27SRafael J. Wysocki static int configure_trip(struct intel_soc_dts_sensor_entry *dts,
1330b28ba27SRafael J. Wysocki int thres_index, enum thermal_trip_type trip_type,
1340b28ba27SRafael J. Wysocki int temp)
1350b28ba27SRafael J. Wysocki {
1360b28ba27SRafael J. Wysocki int ret;
1370b28ba27SRafael J. Wysocki
138cbc28057SRafael J. Wysocki ret = update_trip_temp(dts->sensors, thres_index, temp);
1390b28ba27SRafael J. Wysocki if (ret)
1400b28ba27SRafael J. Wysocki return ret;
1410b28ba27SRafael J. Wysocki
142*4effd28eSRafael J. Wysocki dts->trips[thres_index].temperature = temp;
143*4effd28eSRafael J. Wysocki dts->trips[thres_index].type = trip_type;
1440b28ba27SRafael J. Wysocki
1450b28ba27SRafael J. Wysocki return 0;
1460b28ba27SRafael J. Wysocki }
1470b28ba27SRafael J. Wysocki
sys_set_trip_temp(struct thermal_zone_device * tzd,int trip,int temp)1483e8c4d31SAmit Kucheria static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
1493e8c4d31SAmit Kucheria int temp)
1503e8c4d31SAmit Kucheria {
1515f68d078SDaniel Lezcano struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_priv(tzd);
1523e8c4d31SAmit Kucheria struct intel_soc_dts_sensors *sensors = dts->sensors;
1533e8c4d31SAmit Kucheria int status;
1543e8c4d31SAmit Kucheria
1553e8c4d31SAmit Kucheria if (temp > sensors->tj_max)
1563e8c4d31SAmit Kucheria return -EINVAL;
1573e8c4d31SAmit Kucheria
1583e8c4d31SAmit Kucheria mutex_lock(&sensors->dts_update_lock);
159cbc28057SRafael J. Wysocki status = update_trip_temp(sensors, trip, temp);
1603e8c4d31SAmit Kucheria mutex_unlock(&sensors->dts_update_lock);
1613e8c4d31SAmit Kucheria
1623e8c4d31SAmit Kucheria return status;
1633e8c4d31SAmit Kucheria }
1643e8c4d31SAmit Kucheria
sys_get_curr_temp(struct thermal_zone_device * tzd,int * temp)1653e8c4d31SAmit Kucheria static int sys_get_curr_temp(struct thermal_zone_device *tzd,
1663e8c4d31SAmit Kucheria int *temp)
1673e8c4d31SAmit Kucheria {
1683e8c4d31SAmit Kucheria int status;
1693e8c4d31SAmit Kucheria u32 out;
1705f68d078SDaniel Lezcano struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_priv(tzd);
1713e8c4d31SAmit Kucheria struct intel_soc_dts_sensors *sensors;
1729f00ebf5SWilliam Breathitt Gray unsigned long raw;
1733e8c4d31SAmit Kucheria
1743e8c4d31SAmit Kucheria sensors = dts->sensors;
1753e8c4d31SAmit Kucheria status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
1763e8c4d31SAmit Kucheria SOC_DTS_OFFSET_TEMP, &out);
1773e8c4d31SAmit Kucheria if (status)
1783e8c4d31SAmit Kucheria return status;
1793e8c4d31SAmit Kucheria
1809f00ebf5SWilliam Breathitt Gray raw = out;
1819f00ebf5SWilliam Breathitt Gray out = bitmap_get_value8(&raw, dts->id * 8) - SOC_DTS_TJMAX_ENCODING;
1823e8c4d31SAmit Kucheria *temp = sensors->tj_max - out * 1000;
1833e8c4d31SAmit Kucheria
1843e8c4d31SAmit Kucheria return 0;
1853e8c4d31SAmit Kucheria }
1863e8c4d31SAmit Kucheria
1873e8c4d31SAmit Kucheria static struct thermal_zone_device_ops tzone_ops = {
1883e8c4d31SAmit Kucheria .get_temp = sys_get_curr_temp,
1893e8c4d31SAmit Kucheria .set_trip_temp = sys_set_trip_temp,
1903e8c4d31SAmit Kucheria };
1913e8c4d31SAmit Kucheria
soc_dts_enable(int id)1923e8c4d31SAmit Kucheria static int soc_dts_enable(int id)
1933e8c4d31SAmit Kucheria {
1943e8c4d31SAmit Kucheria u32 out;
1953e8c4d31SAmit Kucheria int ret;
1963e8c4d31SAmit Kucheria
1973e8c4d31SAmit Kucheria ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
1983e8c4d31SAmit Kucheria SOC_DTS_OFFSET_ENABLE, &out);
1993e8c4d31SAmit Kucheria if (ret)
2003e8c4d31SAmit Kucheria return ret;
2013e8c4d31SAmit Kucheria
2023e8c4d31SAmit Kucheria if (!(out & BIT(id))) {
2033e8c4d31SAmit Kucheria out |= BIT(id);
2043e8c4d31SAmit Kucheria ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
2053e8c4d31SAmit Kucheria SOC_DTS_OFFSET_ENABLE, out);
2063e8c4d31SAmit Kucheria if (ret)
2073e8c4d31SAmit Kucheria return ret;
2083e8c4d31SAmit Kucheria }
2093e8c4d31SAmit Kucheria
2103e8c4d31SAmit Kucheria return ret;
2113e8c4d31SAmit Kucheria }
2123e8c4d31SAmit Kucheria
remove_dts_thermal_zone(struct intel_soc_dts_sensor_entry * dts)2133e8c4d31SAmit Kucheria static void remove_dts_thermal_zone(struct intel_soc_dts_sensor_entry *dts)
2143e8c4d31SAmit Kucheria {
2153e8c4d31SAmit Kucheria iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
2163e8c4d31SAmit Kucheria SOC_DTS_OFFSET_ENABLE, dts->store_status);
2173e8c4d31SAmit Kucheria thermal_zone_device_unregister(dts->tzone);
2183e8c4d31SAmit Kucheria }
2193e8c4d31SAmit Kucheria
add_dts_thermal_zone(int id,struct intel_soc_dts_sensor_entry * dts,bool critical_trip)2203e8c4d31SAmit Kucheria static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts,
22102a49aacSRafael J. Wysocki bool critical_trip)
2223e8c4d31SAmit Kucheria {
22302a49aacSRafael J. Wysocki int writable_trip_cnt = SOC_MAX_DTS_TRIPS;
2243e8c4d31SAmit Kucheria char name[10];
2259f00ebf5SWilliam Breathitt Gray unsigned long trip;
2264f164435SRafael J. Wysocki int trip_mask;
2279f00ebf5SWilliam Breathitt Gray unsigned long ptps;
2283e8c4d31SAmit Kucheria u32 store_ptps;
2299f00ebf5SWilliam Breathitt Gray unsigned long i;
2303e8c4d31SAmit Kucheria int ret;
2313e8c4d31SAmit Kucheria
2323e8c4d31SAmit Kucheria /* Store status to restor on exit */
2333e8c4d31SAmit Kucheria ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
2343e8c4d31SAmit Kucheria SOC_DTS_OFFSET_ENABLE, &dts->store_status);
2353e8c4d31SAmit Kucheria if (ret)
2363e8c4d31SAmit Kucheria goto err_ret;
2373e8c4d31SAmit Kucheria
2383e8c4d31SAmit Kucheria dts->id = id;
2394f164435SRafael J. Wysocki
24002a49aacSRafael J. Wysocki if (critical_trip)
24102a49aacSRafael J. Wysocki writable_trip_cnt--;
24202a49aacSRafael J. Wysocki
2439f00ebf5SWilliam Breathitt Gray trip_mask = GENMASK(writable_trip_cnt - 1, 0);
2443e8c4d31SAmit Kucheria
2453e8c4d31SAmit Kucheria /* Check if the writable trip we provide is not used by BIOS */
2463e8c4d31SAmit Kucheria ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
2473e8c4d31SAmit Kucheria SOC_DTS_OFFSET_PTPS, &store_ptps);
2483e8c4d31SAmit Kucheria if (ret)
2493e8c4d31SAmit Kucheria trip_mask = 0;
2503e8c4d31SAmit Kucheria else {
2519f00ebf5SWilliam Breathitt Gray ptps = store_ptps;
2529f00ebf5SWilliam Breathitt Gray for_each_set_clump8(i, trip, &ptps, writable_trip_cnt * 8)
2539f00ebf5SWilliam Breathitt Gray trip_mask &= ~BIT(i / 8);
2543e8c4d31SAmit Kucheria }
2553e8c4d31SAmit Kucheria dts->trip_mask = trip_mask;
2563e8c4d31SAmit Kucheria snprintf(name, sizeof(name), "soc_dts%d", id);
257*4effd28eSRafael J. Wysocki dts->tzone = thermal_zone_device_register_with_trips(name, dts->trips,
258b429b6ffSRafael J. Wysocki SOC_MAX_DTS_TRIPS,
2593e8c4d31SAmit Kucheria trip_mask,
2603e8c4d31SAmit Kucheria dts, &tzone_ops,
2613e8c4d31SAmit Kucheria NULL, 0, 0);
2623e8c4d31SAmit Kucheria if (IS_ERR(dts->tzone)) {
2633e8c4d31SAmit Kucheria ret = PTR_ERR(dts->tzone);
2643e8c4d31SAmit Kucheria goto err_ret;
2653e8c4d31SAmit Kucheria }
266bbcf90c0SAndrzej Pietrasiewicz ret = thermal_zone_device_enable(dts->tzone);
267bbcf90c0SAndrzej Pietrasiewicz if (ret)
268bbcf90c0SAndrzej Pietrasiewicz goto err_enable;
2693e8c4d31SAmit Kucheria
2703e8c4d31SAmit Kucheria ret = soc_dts_enable(id);
2713e8c4d31SAmit Kucheria if (ret)
2723e8c4d31SAmit Kucheria goto err_enable;
2733e8c4d31SAmit Kucheria
2743e8c4d31SAmit Kucheria return 0;
2753e8c4d31SAmit Kucheria err_enable:
2763e8c4d31SAmit Kucheria thermal_zone_device_unregister(dts->tzone);
2773e8c4d31SAmit Kucheria err_ret:
2783e8c4d31SAmit Kucheria return ret;
2793e8c4d31SAmit Kucheria }
2803e8c4d31SAmit Kucheria
intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors * sensors)2813e8c4d31SAmit Kucheria void intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors *sensors)
2823e8c4d31SAmit Kucheria {
2833e8c4d31SAmit Kucheria u32 sticky_out;
2843e8c4d31SAmit Kucheria int status;
2853e8c4d31SAmit Kucheria u32 ptmc_out;
2863e8c4d31SAmit Kucheria unsigned long flags;
2873e8c4d31SAmit Kucheria
2883e8c4d31SAmit Kucheria spin_lock_irqsave(&sensors->intr_notify_lock, flags);
2893e8c4d31SAmit Kucheria
2903e8c4d31SAmit Kucheria status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
2913e8c4d31SAmit Kucheria SOC_DTS_OFFSET_PTMC, &ptmc_out);
2923e8c4d31SAmit Kucheria ptmc_out |= SOC_DTS_PTMC_APIC_DEASSERT_BIT;
2933e8c4d31SAmit Kucheria status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
2943e8c4d31SAmit Kucheria SOC_DTS_OFFSET_PTMC, ptmc_out);
2953e8c4d31SAmit Kucheria
2963e8c4d31SAmit Kucheria status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
2973e8c4d31SAmit Kucheria SOC_DTS_OFFSET_PTTSS, &sticky_out);
2983e8c4d31SAmit Kucheria pr_debug("status %d PTTSS %x\n", status, sticky_out);
2993e8c4d31SAmit Kucheria if (sticky_out & SOC_DTS_TRIP_MASK) {
3003e8c4d31SAmit Kucheria int i;
3013e8c4d31SAmit Kucheria /* reset sticky bit */
3023e8c4d31SAmit Kucheria status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
3033e8c4d31SAmit Kucheria SOC_DTS_OFFSET_PTTSS, sticky_out);
3043e8c4d31SAmit Kucheria spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
3053e8c4d31SAmit Kucheria
3063e8c4d31SAmit Kucheria for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
3073e8c4d31SAmit Kucheria pr_debug("TZD update for zone %d\n", i);
3083e8c4d31SAmit Kucheria thermal_zone_device_update(sensors->soc_dts[i].tzone,
3093e8c4d31SAmit Kucheria THERMAL_EVENT_UNSPECIFIED);
3103e8c4d31SAmit Kucheria }
3113e8c4d31SAmit Kucheria } else
3123e8c4d31SAmit Kucheria spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
3133e8c4d31SAmit Kucheria }
3143e8c4d31SAmit Kucheria EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_interrupt_handler);
3153e8c4d31SAmit Kucheria
dts_trips_reset(struct intel_soc_dts_sensors * sensors,int dts_index)3165bc3da35SRafael J. Wysocki static void dts_trips_reset(struct intel_soc_dts_sensors *sensors, int dts_index)
3175bc3da35SRafael J. Wysocki {
3185bc3da35SRafael J. Wysocki configure_trip(&sensors->soc_dts[dts_index], 0, 0, 0);
3195bc3da35SRafael J. Wysocki configure_trip(&sensors->soc_dts[dts_index], 1, 0, 0);
3205bc3da35SRafael J. Wysocki }
3215bc3da35SRafael J. Wysocki
32202a49aacSRafael 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)32302a49aacSRafael J. Wysocki intel_soc_dts_iosf_init(enum intel_soc_dts_interrupt_type intr_type,
32402a49aacSRafael J. Wysocki bool critical_trip, int crit_offset)
3253e8c4d31SAmit Kucheria {
3263e8c4d31SAmit Kucheria struct intel_soc_dts_sensors *sensors;
327e7fcfe67SYang Li int tj_max;
3283e8c4d31SAmit Kucheria int ret;
3293e8c4d31SAmit Kucheria int i;
3303e8c4d31SAmit Kucheria
3313e8c4d31SAmit Kucheria if (!iosf_mbi_available())
3323e8c4d31SAmit Kucheria return ERR_PTR(-ENODEV);
3333e8c4d31SAmit Kucheria
334955fb871SZhang Rui tj_max = intel_tcc_get_tjmax(-1);
335955fb871SZhang Rui if (tj_max < 0)
336955fb871SZhang Rui return ERR_PTR(tj_max);
3373e8c4d31SAmit Kucheria
3383e8c4d31SAmit Kucheria sensors = kzalloc(sizeof(*sensors), GFP_KERNEL);
3393e8c4d31SAmit Kucheria if (!sensors)
3403e8c4d31SAmit Kucheria return ERR_PTR(-ENOMEM);
3413e8c4d31SAmit Kucheria
3423e8c4d31SAmit Kucheria spin_lock_init(&sensors->intr_notify_lock);
3433e8c4d31SAmit Kucheria mutex_init(&sensors->dts_update_lock);
3443e8c4d31SAmit Kucheria sensors->intr_type = intr_type;
3450bb619f9SHans de Goede sensors->tj_max = tj_max * 1000;
3464f164435SRafael J. Wysocki
3473e8c4d31SAmit Kucheria for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
34802a49aacSRafael J. Wysocki enum thermal_trip_type trip_type;
34902a49aacSRafael J. Wysocki int temp;
35002a49aacSRafael J. Wysocki
3513e8c4d31SAmit Kucheria sensors->soc_dts[i].sensors = sensors;
3523e8c4d31SAmit Kucheria
3530b28ba27SRafael J. Wysocki ret = configure_trip(&sensors->soc_dts[i], 0,
3540b28ba27SRafael J. Wysocki THERMAL_TRIP_PASSIVE, 0);
3553e8c4d31SAmit Kucheria if (ret)
35651f2aaf0SRafael J. Wysocki goto err_reset_trips;
3573e8c4d31SAmit Kucheria
35802a49aacSRafael J. Wysocki if (critical_trip) {
35902a49aacSRafael J. Wysocki trip_type = THERMAL_TRIP_CRITICAL;
36002a49aacSRafael J. Wysocki temp = sensors->tj_max - crit_offset;
36102a49aacSRafael J. Wysocki } else {
36202a49aacSRafael J. Wysocki trip_type = THERMAL_TRIP_PASSIVE;
36302a49aacSRafael J. Wysocki temp = 0;
36402a49aacSRafael J. Wysocki }
36502a49aacSRafael J. Wysocki ret = configure_trip(&sensors->soc_dts[i], 1, trip_type, temp);
3663e8c4d31SAmit Kucheria if (ret)
36751f2aaf0SRafael J. Wysocki goto err_reset_trips;
36851f2aaf0SRafael J. Wysocki }
36951f2aaf0SRafael J. Wysocki
37051f2aaf0SRafael J. Wysocki for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
37102a49aacSRafael J. Wysocki ret = add_dts_thermal_zone(i, &sensors->soc_dts[i], critical_trip);
37251f2aaf0SRafael J. Wysocki if (ret)
3733e8c4d31SAmit Kucheria goto err_remove_zone;
3743e8c4d31SAmit Kucheria }
3753e8c4d31SAmit Kucheria
3763e8c4d31SAmit Kucheria return sensors;
37751f2aaf0SRafael J. Wysocki
3783e8c4d31SAmit Kucheria err_remove_zone:
3793e8c4d31SAmit Kucheria for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i)
3803e8c4d31SAmit Kucheria remove_dts_thermal_zone(&sensors->soc_dts[i]);
3813e8c4d31SAmit Kucheria
38251f2aaf0SRafael J. Wysocki err_reset_trips:
3835bc3da35SRafael J. Wysocki for (i = 0; i < SOC_MAX_DTS_SENSORS; i++)
3845bc3da35SRafael J. Wysocki dts_trips_reset(sensors, i);
38551f2aaf0SRafael J. Wysocki
3863e8c4d31SAmit Kucheria kfree(sensors);
3873e8c4d31SAmit Kucheria return ERR_PTR(ret);
3883e8c4d31SAmit Kucheria }
3893e8c4d31SAmit Kucheria EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_init);
3903e8c4d31SAmit Kucheria
intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors * sensors)3913e8c4d31SAmit Kucheria void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors)
3923e8c4d31SAmit Kucheria {
3933e8c4d31SAmit Kucheria int i;
3943e8c4d31SAmit Kucheria
3953e8c4d31SAmit Kucheria for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
39651f2aaf0SRafael J. Wysocki remove_dts_thermal_zone(&sensors->soc_dts[i]);
3975bc3da35SRafael J. Wysocki dts_trips_reset(sensors, i);
3983e8c4d31SAmit Kucheria }
3993e8c4d31SAmit Kucheria kfree(sensors);
4003e8c4d31SAmit Kucheria }
4013e8c4d31SAmit Kucheria EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_exit);
4023e8c4d31SAmit Kucheria
403955fb871SZhang Rui MODULE_IMPORT_NS(INTEL_TCC);
4043e8c4d31SAmit Kucheria MODULE_LICENSE("GPL v2");
405