^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * thermal_helpers.c - helper functions to handle thermal devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2016 Eduardo Valentin <edubezval@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Highly based on original thermal_core.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2008 Intel Corp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <trace/events/thermal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "thermal_core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) int get_tz_trend(struct thermal_zone_device *tz, int trip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) enum thermal_trend trend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (tz->emul_temperature || !tz->ops->get_trend ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) tz->ops->get_trend(tz, trip, &trend)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (tz->temperature > tz->last_temperature)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) trend = THERMAL_TREND_RAISING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) else if (tz->temperature < tz->last_temperature)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) trend = THERMAL_TREND_DROPPING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) trend = THERMAL_TREND_STABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return trend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) EXPORT_SYMBOL(get_tz_trend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct thermal_instance *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) get_thermal_instance(struct thermal_zone_device *tz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct thermal_cooling_device *cdev, int trip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct thermal_instance *pos = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct thermal_instance *target_instance = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) mutex_lock(&tz->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) mutex_lock(&cdev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) list_for_each_entry(pos, &tz->thermal_instances, tz_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) target_instance = pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) mutex_unlock(&cdev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) mutex_unlock(&tz->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return target_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) EXPORT_SYMBOL(get_thermal_instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * thermal_zone_get_temp() - returns the temperature of a thermal zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * @tz: a valid pointer to a struct thermal_zone_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * @temp: a valid pointer to where to store the resulting temperature.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * When a valid thermal zone reference is passed, it will fetch its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * temperature and fill @temp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * Return: On success returns 0, an error code otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int crit_temp = INT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) enum thermal_trip_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (!tz || IS_ERR(tz) || !tz->ops->get_temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) mutex_lock(&tz->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ret = tz->ops->get_temp(tz, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (IS_ENABLED(CONFIG_THERMAL_EMULATION) && tz->emul_temperature) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) for (count = 0; count < tz->trips; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) ret = tz->ops->get_trip_type(tz, count, &type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (!ret && type == THERMAL_TRIP_CRITICAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ret = tz->ops->get_trip_temp(tz, count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) &crit_temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * Only allow emulating a temperature when the real temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * is below the critical temperature so that the emulation code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * cannot hide critical conditions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (!ret && *temp < crit_temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) *temp = tz->emul_temperature;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) mutex_unlock(&tz->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * thermal_zone_set_trips - Computes the next trip points for the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * @tz: a pointer to a thermal zone device structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * The function computes the next temperature boundaries by browsing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * the trip points. The result is the closer low and high trip points
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * to the current temperature. These values are passed to the backend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * driver to let it set its own notification mechanism (usually an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * interrupt).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * It does not return a value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) void thermal_zone_set_trips(struct thermal_zone_device *tz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int low = -INT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) int high = INT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int trip_temp, hysteresis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) mutex_lock(&tz->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (!tz->ops->set_trips || !tz->ops->get_trip_hyst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) for (i = 0; i < tz->trips; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int trip_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) tz->ops->get_trip_temp(tz, i, &trip_temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) tz->ops->get_trip_hyst(tz, i, &hysteresis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) trip_low = trip_temp - hysteresis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (trip_low < tz->temperature && trip_low > low)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) low = trip_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (trip_temp > tz->temperature && trip_temp < high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) high = trip_temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* No need to change trip points */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (tz->prev_low_trip == low && tz->prev_high_trip == high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) tz->prev_low_trip = low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) tz->prev_high_trip = high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) dev_dbg(&tz->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) "new temperature boundaries: %d < x < %d\n", low, high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * Set a temperature window. When this window is left the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * must inform the thermal core via thermal_zone_device_update.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) ret = tz->ops->set_trips(tz, low, high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) dev_err(&tz->device, "Failed to set trips: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) mutex_unlock(&tz->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static void thermal_cdev_set_cur_state(struct thermal_cooling_device *cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) int target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (cdev->ops->set_cur_state(cdev, target))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) thermal_notify_cdev_state_update(cdev->id, target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) thermal_cooling_device_stats_update(cdev, target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) void thermal_cdev_update(struct thermal_cooling_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct thermal_instance *instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) unsigned long target = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) mutex_lock(&cdev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /* cooling device is updated*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (cdev->updated) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) mutex_unlock(&cdev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* Make sure cdev enters the deepest cooling state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) dev_dbg(&cdev->device, "zone%d->target=%lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) instance->tz->id, instance->target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (instance->target == THERMAL_NO_TARGET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (instance->target > target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) target = instance->target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) thermal_cdev_set_cur_state(cdev, target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) cdev->updated = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) mutex_unlock(&cdev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) trace_cdev_update(cdev, target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) dev_dbg(&cdev->device, "set to state %lu\n", target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) EXPORT_SYMBOL(thermal_cdev_update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * thermal_zone_get_slope - return the slope attribute of the thermal zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * @tz: thermal zone device with the slope attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * Return: If the thermal zone device has a slope attribute, return it, else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * return 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) int thermal_zone_get_slope(struct thermal_zone_device *tz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (tz && tz->tzp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return tz->tzp->slope;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) EXPORT_SYMBOL_GPL(thermal_zone_get_slope);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * thermal_zone_get_offset - return the offset attribute of the thermal zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * @tz: thermal zone device with the offset attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * Return: If the thermal zone device has a offset attribute, return it, else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * return 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int thermal_zone_get_offset(struct thermal_zone_device *tz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (tz && tz->tzp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return tz->tzp->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) EXPORT_SYMBOL_GPL(thermal_zone_get_offset);