/* * include/linux/therm_est.h * * Copyright (c) 2010-2021, NVIDIA CORPORATION. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #ifndef _LINUX_THERM_EST_H #define _LINUX_THERM_EST_H #include #include #include #define HIST_LEN (20) #define MAX_ACTIVE_STATES 10 #define MAX_TIMER_TRIPS 10 #define MAX_SUBDEVICE_GROUP 2 struct therm_est_sub_thz { struct thermal_zone_device *thz; long hist[HIST_LEN]; }; struct therm_est_coeffs { long toffset; s32 (*coeffs)[HIST_LEN]; }; struct therm_est_subdevice { struct therm_est_sub_thz *sub_thz; struct therm_est_coeffs *coeffs_set; int num_devs; int num_coeffs; int active_coeffs; int ntemp; }; /* * Timer trip provides a way to change trip temp dynamically based on timestamp * when the trip is enabled. * - Timer trip can be various numbers on a trip. * - If the trip is enabled, then timer will be started with time_after delay * in the corresponding timer trip. After the timer expires, trip_temp and * hysteresis in the corresponding timer trip will be used to trip_temp for * the trip. * - When the timer has expired, index of timer trip will be increased a step * and then start the timer with time_after delay in newly indexed timer trip. * - When temp is below trip temp, index of timer trip will be decreased a step * and then stop the timer and start the timer with time_after delay in newly * indexed timer trip. * - The timer will be stopped if there is no more next timer trip on the trip, * or the trip is disabled. */ struct therm_est_timer_trip { long time_after; /* in msec */ long trip_temp; long hysteresis; }; struct therm_est_timer_trip_info { int trip; /* trip point on thermal zone to apply timer trip */ int num_timers; struct therm_est_timer_trip timers[MAX_TIMER_TRIPS]; int cur; /* index of current timer trip */ s64 last_tripped; /* timestamp when the trip is enabled, in msec */ }; struct therm_est_data { /* trip point info */ int num_trips; struct thermal_trip_info *trips; /* timer trip info */ int num_timer_trips; struct therm_est_timer_trip_info *timer_trips; /* zone parameters */ struct thermal_zone_params *tzp; long polling_period; int passive_delay; int tc1; int tc2; struct therm_est_subdevice subdevice; int use_activator; }; struct therm_fan_est_subdevice { const char *dev_data; int (*get_temp)(const char *, int *); int group; /* * as we read coeffs array from the device tree, * specify type that has known width - 32 bits * * 'long' does not work, as its size if arch-dependent */ s32 coeffs[HIST_LEN]; int hist[HIST_LEN]; }; struct therm_fan_est_data { long toffset; long polling_period; int ndevs; char *cdev_type; int active_trip_temps[MAX_ACTIVE_STATES]; int active_hysteresis[MAX_ACTIVE_STATES]; struct thermal_zone_params *tzp; struct therm_fan_est_subdevice devs[]; }; struct fan_dev_data { int next_state; int active_steps; int *fan_rpm; int *fan_pwm; int *fan_rru; int *fan_rrd; int *fan_state_cap_lookup; int num_profiles; int current_profile; const char **fan_profile_names; int **fan_profile_pwms; int *fan_profile_caps; struct workqueue_struct *workqueue; int fan_temp_control_flag; struct pwm_device *pwm_dev; bool pwm_legacy_api; int fan_cap_pwm; int fan_cur_pwm; int next_target_pwm; struct thermal_cooling_device *cdev; struct delayed_work fan_ramp_work; struct delayed_work fan_hyst_work; int step_time; long long precision_multiplier; struct mutex fan_state_lock; int pwm_period; int fan_pwm_max; struct device *dev; int tach_gpio; int tach_irq; atomic_t tach_enabled; int fan_state_cap; int pwm_gpio; int pwm_id; int fan_startup_pwm; int fan_startup_time; bool fan_kickstart; /*flag to check if fan is kickstart*/ bool kickstart_en; /*flag to check if kickstart feature is enabled*/ enum pwm_polarity fan_pwm_polarity; int suspend_state; const char *name; const char *regulator_name; struct regulator *fan_reg; bool is_fan_reg_enabled; struct dentry *debugfs_root; /* for tach feedback */ atomic64_t rpm_measured; struct delayed_work fan_tach_work; struct workqueue_struct *tach_workqueue; int tach_period; spinlock_t irq_lock; int irq_count; u64 first_irq; u64 last_irq; u64 old_irq; struct device_node *of_node_tach; bool use_tach_feedback; int rpm_diff_tolerance; int fan_rpm_target_hit_count; int fan_rpm_ramp_index; int next_target_rpm; int fan_ramp_time_ms; struct delayed_work fan_ramp_pwm_work; struct delayed_work fan_ramp_rpm_work; struct device *pwm_tach_dev; struct completion pwm_set; bool fan_rpm_in_limits; int rpm_valid_retry_delay; int rpm_invalid_retry_delay; int rpm_valid_retry_count; bool continuous_gov; bool is_tmargin; bool is_always_on; }; #define DEBUG 0 #define MULTIQP (100) #define DEFERRED_RESUME_TIME 3000 #define THERMAL_GOV_PID "pid_thermal_gov" #define THERMAL_CONTINUOUS_GOV "continuous_therm_gov" struct therm_fan_estimator { long cur_temp; long pre_temp; #if DEBUG long cur_temp_debug; #endif long polling_period; struct workqueue_struct *workqueue; struct delayed_work therm_fan_est_work; long toffset; int ntemp; int ndevs; struct therm_fan_est_subdevice *devs; struct thermal_zone_device *thz; int current_trip_level; const char *cdev_type; rwlock_t state_lock; int num_profiles; int current_profile; const char **fan_profile_names; s32 **fan_profile_trip_temps; s32 **fan_profile_trip_hysteresis; s32 active_trip_temps[MAX_ACTIVE_STATES]; s32 active_hysteresis[MAX_ACTIVE_STATES]; struct thermal_zone_params *tzp; int num_resources; int trip_length; const char *name; bool is_pid_gov; bool reset_trip_index; /* allow cooling device to turn off at higher temperature if sleep */ bool sleep_mode; int nonsleep_hyst; bool use_tmargin; long crit_temp[MAX_SUBDEVICE_GROUP]; bool is_continuous_gov; }; #if IS_ENABLED(CONFIG_GENERIC_PWM_TACHOMETER) int pwm_tach_capture_rpm(struct device *dev); struct device *pwm_get_tach_dev(void); #else static inline int pwm_tach_capture_rpm(struct device *dev) { return 0; } static inline struct device *pwm_get_tach_dev(void) { return NULL; } #endif #if IS_ENABLED(CONFIG_THERMAL_GOV_CONTINUOUS) int continuous_thermal_gov_update_params(struct thermal_zone_params *tzp, struct device_node *np); #else static inline int continuous_thermal_gov_update_params( struct thermal_zone_params *tzp, struct device_node *np) { return 0; } #endif #endif /* _LINUX_THERM_EST_H */