diff options
Diffstat (limited to 'drivers/thermal')
-rw-r--r-- | drivers/thermal/cpufreq_cooling.c | 2 | ||||
-rw-r--r-- | drivers/thermal/gov_bang_bang.c | 11 | ||||
-rw-r--r-- | drivers/thermal/gov_fair_share.c | 16 | ||||
-rw-r--r-- | drivers/thermal/gov_power_allocator.c | 71 | ||||
-rw-r--r-- | drivers/thermal/gov_step_wise.c | 16 | ||||
-rw-r--r-- | drivers/thermal/intel/int340x_thermal/int3402_thermal.c | 3 | ||||
-rw-r--r-- | drivers/thermal/intel/x86_pkg_temp_thermal.c | 1 | ||||
-rw-r--r-- | drivers/thermal/mediatek/lvts_thermal.c | 71 | ||||
-rw-r--r-- | drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 43 | ||||
-rw-r--r-- | drivers/thermal/qoriq_thermal.c | 13 | ||||
-rw-r--r-- | drivers/thermal/rockchip_thermal.c | 1 | ||||
-rw-r--r-- | drivers/thermal/thermal_core.c | 33 | ||||
-rw-r--r-- | drivers/thermal/thermal_core.h | 5 | ||||
-rw-r--r-- | drivers/thermal/thermal_helpers.c | 5 | ||||
-rw-r--r-- | drivers/thermal/thermal_of.c | 53 | ||||
-rw-r--r-- | drivers/thermal/thermal_sysfs.c | 9 |
16 files changed, 219 insertions, 134 deletions
diff --git a/drivers/thermal/cpufreq_cooling.c b/drivers/thermal/cpufreq_cooling.c index 280071be30b1..6b7ab1814c12 100644 --- a/drivers/thermal/cpufreq_cooling.c +++ b/drivers/thermal/cpufreq_cooling.c @@ -57,8 +57,6 @@ struct time_in_idle { * @max_level: maximum cooling level. One less than total number of valid * cpufreq frequencies. * @em: Reference on the Energy Model of the device - * @cdev: thermal_cooling_device pointer to keep track of the - * registered cooling device. * @policy: cpufreq policy. * @cooling_ops: cpufreq callbacks to thermal cooling device ops * @idle_time: idle time stats diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c index 863e7a4272e6..b887e48e8c7e 100644 --- a/drivers/thermal/gov_bang_bang.c +++ b/drivers/thermal/gov_bang_bang.c @@ -67,6 +67,7 @@ static void bang_bang_control(struct thermal_zone_device *tz, const struct thermal_trip *trip, bool crossed_up) { + const struct thermal_trip_desc *td = trip_to_trip_desc(trip); struct thermal_instance *instance; lockdep_assert_held(&tz->lock); @@ -75,10 +76,8 @@ static void bang_bang_control(struct thermal_zone_device *tz, thermal_zone_trip_id(tz, trip), trip->temperature, tz->temperature, trip->hysteresis); - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { - if (instance->trip == trip) - bang_bang_set_instance_target(instance, crossed_up); - } + list_for_each_entry(instance, &td->thermal_instances, trip_node) + bang_bang_set_instance_target(instance, crossed_up); } static void bang_bang_manage(struct thermal_zone_device *tz) @@ -104,8 +103,8 @@ static void bang_bang_manage(struct thermal_zone_device *tz) * to the thermal zone temperature and the trip point threshold. */ turn_on = tz->temperature >= td->threshold; - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { - if (!instance->initialized && instance->trip == trip) + list_for_each_entry(instance, &td->thermal_instances, trip_node) { + if (!instance->initialized) bang_bang_set_instance_target(instance, turn_on); } } diff --git a/drivers/thermal/gov_fair_share.c b/drivers/thermal/gov_fair_share.c index ce0ea571ed67..d37d57d48c38 100644 --- a/drivers/thermal/gov_fair_share.c +++ b/drivers/thermal/gov_fair_share.c @@ -44,7 +44,7 @@ static int get_trip_level(struct thermal_zone_device *tz) /** * fair_share_throttle - throttles devices associated with the given zone * @tz: thermal_zone_device - * @trip: trip point + * @td: trip point descriptor * @trip_level: number of trips crossed by the zone temperature * * Throttling Logic: This uses three parameters to calculate the new @@ -61,29 +61,23 @@ static int get_trip_level(struct thermal_zone_device *tz) * new_state of cooling device = P3 * P2 * P1 */ static void fair_share_throttle(struct thermal_zone_device *tz, - const struct thermal_trip *trip, + const struct thermal_trip_desc *td, int trip_level) { struct thermal_instance *instance; int total_weight = 0; int nr_instances = 0; - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { - if (instance->trip != trip) - continue; - + list_for_each_entry(instance, &td->thermal_instances, trip_node) { total_weight += instance->weight; nr_instances++; } - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { + list_for_each_entry(instance, &td->thermal_instances, trip_node) { struct thermal_cooling_device *cdev = instance->cdev; u64 dividend; u32 divisor; - if (instance->trip != trip) - continue; - dividend = trip_level; dividend *= cdev->max_state; divisor = tz->num_trips; @@ -116,7 +110,7 @@ static void fair_share_manage(struct thermal_zone_device *tz) trip->type == THERMAL_TRIP_HOT) continue; - fair_share_throttle(tz, trip, trip_level); + fair_share_throttle(tz, td, trip_level); } } diff --git a/drivers/thermal/gov_power_allocator.c b/drivers/thermal/gov_power_allocator.c index 1b2345a697c5..90b4bfd9237b 100644 --- a/drivers/thermal/gov_power_allocator.c +++ b/drivers/thermal/gov_power_allocator.c @@ -97,11 +97,9 @@ struct power_allocator_params { struct power_actor *power; }; -static bool power_actor_is_valid(struct power_allocator_params *params, - struct thermal_instance *instance) +static bool power_actor_is_valid(struct thermal_instance *instance) { - return (instance->trip == params->trip_max && - cdev_is_power_actor(instance->cdev)); + return cdev_is_power_actor(instance->cdev); } /** @@ -118,13 +116,14 @@ static bool power_actor_is_valid(struct power_allocator_params *params, static u32 estimate_sustainable_power(struct thermal_zone_device *tz) { struct power_allocator_params *params = tz->governor_data; + const struct thermal_trip_desc *td = trip_to_trip_desc(params->trip_max); struct thermal_cooling_device *cdev; struct thermal_instance *instance; u32 sustainable_power = 0; u32 min_power; - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { - if (!power_actor_is_valid(params, instance)) + list_for_each_entry(instance, &td->thermal_instances, trip_node) { + if (!power_actor_is_valid(instance)) continue; cdev = instance->cdev; @@ -364,7 +363,7 @@ static void divvy_up_power(struct power_actor *power, int num_actors, for (i = 0; i < num_actors; i++) { struct power_actor *pa = &power[i]; - u64 req_range = (u64)pa->req_power * power_range; + u64 req_range = (u64)pa->weighted_req_power * power_range; pa->granted_power = DIV_ROUND_CLOSEST_ULL(req_range, total_req_power); @@ -400,6 +399,7 @@ static void divvy_up_power(struct power_actor *power, int num_actors, static void allocate_power(struct thermal_zone_device *tz, int control_temp) { struct power_allocator_params *params = tz->governor_data; + const struct thermal_trip_desc *td = trip_to_trip_desc(params->trip_max); unsigned int num_actors = params->num_actors; struct power_actor *power = params->power; struct thermal_cooling_device *cdev; @@ -417,10 +417,10 @@ static void allocate_power(struct thermal_zone_device *tz, int control_temp) /* Clean all buffers for new power estimations */ memset(power, 0, params->buffer_size); - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { + list_for_each_entry(instance, &td->thermal_instances, trip_node) { struct power_actor *pa = &power[i]; - if (!power_actor_is_valid(params, instance)) + if (!power_actor_is_valid(instance)) continue; cdev = instance->cdev; @@ -454,10 +454,10 @@ static void allocate_power(struct thermal_zone_device *tz, int control_temp) power_range); i = 0; - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { + list_for_each_entry(instance, &td->thermal_instances, trip_node) { struct power_actor *pa = &power[i]; - if (!power_actor_is_valid(params, instance)) + if (!power_actor_is_valid(instance)) continue; power_actor_set_power(instance->cdev, instance, @@ -538,12 +538,13 @@ static void reset_pid_controller(struct power_allocator_params *params) static void allow_maximum_power(struct thermal_zone_device *tz) { struct power_allocator_params *params = tz->governor_data; + const struct thermal_trip_desc *td = trip_to_trip_desc(params->trip_max); struct thermal_cooling_device *cdev; struct thermal_instance *instance; u32 req_power; - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { - if (!power_actor_is_valid(params, instance)) + list_for_each_entry(instance, &td->thermal_instances, trip_node) { + if (!power_actor_is_valid(instance)) continue; cdev = instance->cdev; @@ -581,13 +582,16 @@ static void allow_maximum_power(struct thermal_zone_device *tz) static int check_power_actors(struct thermal_zone_device *tz, struct power_allocator_params *params) { + const struct thermal_trip_desc *td; struct thermal_instance *instance; int ret = 0; - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { - if (instance->trip != params->trip_max) - continue; + if (!params->trip_max) + return 0; + + td = trip_to_trip_desc(params->trip_max); + list_for_each_entry(instance, &td->thermal_instances, trip_node) { if (!cdev_is_power_actor(instance->cdev)) { dev_warn(&tz->device, "power_allocator: %s is not a power actor\n", instance->cdev->type); @@ -631,30 +635,43 @@ clean_state: return ret; } +static void power_allocator_update_weight(struct power_allocator_params *params) +{ + const struct thermal_trip_desc *td; + struct thermal_instance *instance; + + if (!params->trip_max) + return; + + td = trip_to_trip_desc(params->trip_max); + + params->total_weight = 0; + list_for_each_entry(instance, &td->thermal_instances, trip_node) + if (power_actor_is_valid(instance)) + params->total_weight += instance->weight; +} + static void power_allocator_update_tz(struct thermal_zone_device *tz, enum thermal_notify_event reason) { struct power_allocator_params *params = tz->governor_data; + const struct thermal_trip_desc *td = trip_to_trip_desc(params->trip_max); struct thermal_instance *instance; int num_actors = 0; switch (reason) { case THERMAL_TZ_BIND_CDEV: case THERMAL_TZ_UNBIND_CDEV: - list_for_each_entry(instance, &tz->thermal_instances, tz_node) - if (power_actor_is_valid(params, instance)) + list_for_each_entry(instance, &td->thermal_instances, trip_node) + if (power_actor_is_valid(instance)) num_actors++; - if (num_actors == params->num_actors) - return; + if (num_actors != params->num_actors) + allocate_actors_buffer(params, num_actors); - allocate_actors_buffer(params, num_actors); - break; + fallthrough; case THERMAL_INSTANCE_WEIGHT_CHANGED: - params->total_weight = 0; - list_for_each_entry(instance, &tz->thermal_instances, tz_node) - if (power_actor_is_valid(params, instance)) - params->total_weight += instance->weight; + power_allocator_update_weight(params); break; default: break; @@ -720,6 +737,8 @@ static int power_allocator_bind(struct thermal_zone_device *tz) tz->governor_data = params; + power_allocator_update_weight(params); + return 0; free_params: diff --git a/drivers/thermal/gov_step_wise.c b/drivers/thermal/gov_step_wise.c index fd5527188cf9..ea4bf88d37f3 100644 --- a/drivers/thermal/gov_step_wise.c +++ b/drivers/thermal/gov_step_wise.c @@ -66,9 +66,10 @@ static unsigned long get_target_state(struct thermal_instance *instance, } static void thermal_zone_trip_update(struct thermal_zone_device *tz, - const struct thermal_trip *trip, + const struct thermal_trip_desc *td, int trip_threshold) { + const struct thermal_trip *trip = &td->trip; enum thermal_trend trend = get_tz_trend(tz, trip); int trip_id = thermal_zone_trip_id(tz, trip); struct thermal_instance *instance; @@ -82,12 +83,9 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n", trip_id, trip->type, trip_threshold, trend, throttle); - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { + list_for_each_entry(instance, &td->thermal_instances, trip_node) { int old_target; - if (instance->trip != trip) - continue; - old_target = instance->target; instance->target = get_target_state(instance, trend, throttle); @@ -127,11 +125,13 @@ static void step_wise_manage(struct thermal_zone_device *tz) trip->type == THERMAL_TRIP_HOT) continue; - thermal_zone_trip_update(tz, trip, td->threshold); + thermal_zone_trip_update(tz, td, td->threshold); } - list_for_each_entry(instance, &tz->thermal_instances, tz_node) - thermal_cdev_update(instance->cdev); + for_each_trip_desc(tz, td) { + list_for_each_entry(instance, &td->thermal_instances, trip_node) + thermal_cdev_update(instance->cdev); + } } static struct thermal_governor thermal_gov_step_wise = { diff --git a/drivers/thermal/intel/int340x_thermal/int3402_thermal.c b/drivers/thermal/intel/int340x_thermal/int3402_thermal.c index ab8bfb5a3946..40ab6b2d4fb0 100644 --- a/drivers/thermal/intel/int340x_thermal/int3402_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3402_thermal.c @@ -45,6 +45,9 @@ static int int3402_thermal_probe(struct platform_device *pdev) struct int3402_thermal_data *d; int ret; + if (!adev) + return -ENODEV; + if (!acpi_has_method(adev->handle, "_TMP")) return -ENODEV; diff --git a/drivers/thermal/intel/x86_pkg_temp_thermal.c b/drivers/thermal/intel/x86_pkg_temp_thermal.c index 65b33b56a9be..8c44f378b61e 100644 --- a/drivers/thermal/intel/x86_pkg_temp_thermal.c +++ b/drivers/thermal/intel/x86_pkg_temp_thermal.c @@ -329,6 +329,7 @@ static int pkg_temp_thermal_device_add(unsigned int cpu) tj_max = intel_tcc_get_tjmax(cpu); if (tj_max < 0) return tj_max; + tj_max *= 1000; zonedev = kzalloc(sizeof(*zonedev), GFP_KERNEL); if (!zonedev) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index 1997e91bb3be..ae063d1bc95f 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -65,7 +65,6 @@ #define LVTS_HW_FILTER 0x0 #define LVTS_TSSEL_CONF 0x13121110 #define LVTS_CALSCALE_CONF 0x300 -#define LVTS_MONINT_CONF 0x8300318C #define LVTS_MONINT_OFFSET_SENSOR0 0xC #define LVTS_MONINT_OFFSET_SENSOR1 0x180 @@ -91,8 +90,6 @@ #define LVTS_MSR_READ_TIMEOUT_US 400 #define LVTS_MSR_READ_WAIT_US (LVTS_MSR_READ_TIMEOUT_US / 2) -#define LVTS_HW_TSHUT_TEMP 105000 - #define LVTS_MINIMUM_THRESHOLD 20000 static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT; @@ -145,7 +142,6 @@ struct lvts_ctrl { struct lvts_sensor sensors[LVTS_SENSOR_MAX]; const struct lvts_data *lvts_data; u32 calibration[LVTS_SENSOR_MAX]; - u32 hw_tshut_raw_temp; u8 valid_sensor_mask; int mode; void __iomem *base; @@ -213,6 +209,13 @@ static const struct debugfs_reg32 lvts_regs[] = { LVTS_DEBUG_FS_REGS(LVTS_CLKEN), }; +static void lvts_debugfs_exit(void *data) +{ + struct lvts_domain *lvts_td = data; + + debugfs_remove_recursive(lvts_td->dom_dentry); +} + static int lvts_debugfs_init(struct device *dev, struct lvts_domain *lvts_td) { struct debugfs_regset32 *regset; @@ -245,12 +248,7 @@ static int lvts_debugfs_init(struct device *dev, struct lvts_domain *lvts_td) debugfs_create_regset32("registers", 0400, dentry, regset); } - return 0; -} - -static void lvts_debugfs_exit(struct lvts_domain *lvts_td) -{ - debugfs_remove_recursive(lvts_td->dom_dentry); + return devm_add_action_or_reset(dev, lvts_debugfs_exit, lvts_td); } #else @@ -261,8 +259,6 @@ static inline int lvts_debugfs_init(struct device *dev, return 0; } -static void lvts_debugfs_exit(struct lvts_domain *lvts_td) { } - #endif static int lvts_raw_to_temp(u32 raw_temp, int temp_factor) @@ -837,14 +833,6 @@ static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td, */ lvts_ctrl[i].mode = lvts_data->lvts_ctrl[i].mode; - /* - * The temperature to raw temperature must be done - * after initializing the calibration. - */ - lvts_ctrl[i].hw_tshut_raw_temp = - lvts_temp_to_raw(LVTS_HW_TSHUT_TEMP, - lvts_data->temp_factor); - lvts_ctrl[i].low_thresh = INT_MIN; lvts_ctrl[i].high_thresh = INT_MIN; } @@ -860,6 +848,32 @@ static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td, return 0; } +static void lvts_ctrl_monitor_enable(struct device *dev, struct lvts_ctrl *lvts_ctrl, bool enable) +{ + /* + * Bitmaps to enable each sensor on filtered mode in the MONCTL0 + * register. + */ + static const u8 sensor_filt_bitmap[] = { BIT(0), BIT(1), BIT(2), BIT(3) }; + u32 sensor_map = 0; + int i; + + if (lvts_ctrl->mode != LVTS_MSR_FILTERED_MODE) + return; + + if (enable) { + lvts_for_each_valid_sensor(i, lvts_ctrl) + sensor_map |= sensor_filt_bitmap[i]; + } + + /* + * Bits: + * 9: Single point access flow + * 0-3: Enable sensing point 0-3 + */ + writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base)); +} + /* * At this point the configuration register is the only place in the * driver where we write multiple values. Per hardware constraint, @@ -893,7 +907,6 @@ static int lvts_irq_init(struct lvts_ctrl *lvts_ctrl) * 10 : Selected sensor with bits 19-18 * 11 : Reserved */ - writel(BIT(16), LVTS_PROTCTL(lvts_ctrl->base)); /* * LVTS_PROTTA : Stage 1 temperature threshold @@ -906,8 +919,8 @@ static int lvts_irq_init(struct lvts_ctrl *lvts_ctrl) * * writel(0x0, LVTS_PROTTA(lvts_ctrl->base)); * writel(0x0, LVTS_PROTTB(lvts_ctrl->base)); + * writel(0x0, LVTS_PROTTC(lvts_ctrl->base)); */ - writel(lvts_ctrl->hw_tshut_raw_temp, LVTS_PROTTC(lvts_ctrl->base)); /* * LVTS_MONINT : Interrupt configuration register @@ -915,7 +928,7 @@ static int lvts_irq_init(struct lvts_ctrl *lvts_ctrl) * The LVTS_MONINT register layout is the same as the LVTS_MONINTSTS * register, except we set the bits to enable the interrupt. */ - writel(LVTS_MONINT_CONF, LVTS_MONINT(lvts_ctrl->base)); + writel(0, LVTS_MONINT(lvts_ctrl->base)); return 0; } @@ -1339,8 +1352,6 @@ static void lvts_remove(struct platform_device *pdev) for (i = 0; i < lvts_td->num_lvts_ctrl; i++) lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false); - - lvts_debugfs_exit(lvts_td); } static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] = { @@ -1381,8 +1392,11 @@ static int lvts_suspend(struct device *dev) lvts_td = dev_get_drvdata(dev); - for (i = 0; i < lvts_td->num_lvts_ctrl; i++) + for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { + lvts_ctrl_monitor_enable(dev, &lvts_td->lvts_ctrl[i], false); + usleep_range(100, 200); lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false); + } clk_disable_unprepare(lvts_td->clk); @@ -1400,8 +1414,11 @@ static int lvts_resume(struct device *dev) if (ret) return ret; - for (i = 0; i < lvts_td->num_lvts_ctrl; i++) + for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], true); + usleep_range(100, 200); + lvts_ctrl_monitor_enable(dev, &lvts_td->lvts_ctrl[i], true); + } return 0; } diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c index c2d59cbfaea9..a575585c737b 100644 --- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c +++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2011-2015, 2017, 2020, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include <linux/bitops.h> @@ -16,6 +17,7 @@ #include "../thermal_hwmon.h" +#define QPNP_TM_REG_DIG_MINOR 0x00 #define QPNP_TM_REG_DIG_MAJOR 0x01 #define QPNP_TM_REG_TYPE 0x04 #define QPNP_TM_REG_SUBTYPE 0x05 @@ -31,7 +33,7 @@ #define STATUS_GEN2_STATE_MASK GENMASK(6, 4) #define STATUS_GEN2_STATE_SHIFT 4 -#define SHUTDOWN_CTRL1_OVERRIDE_S2 BIT(6) +#define SHUTDOWN_CTRL1_OVERRIDE_STAGE2 BIT(6) #define SHUTDOWN_CTRL1_THRESHOLD_MASK GENMASK(1, 0) #define SHUTDOWN_CTRL1_RATE_25HZ BIT(3) @@ -78,6 +80,7 @@ struct qpnp_tm_chip { /* protects .thresh, .stage and chip registers */ struct mutex lock; bool initialized; + bool require_stage2_shutdown; struct iio_channel *adc; const long (*temp_map)[THRESH_COUNT][STAGE_COUNT]; @@ -220,13 +223,13 @@ static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip, { long stage2_threshold_min = (*chip->temp_map)[THRESH_MIN][1]; long stage2_threshold_max = (*chip->temp_map)[THRESH_MAX][1]; - bool disable_s2_shutdown = false; + bool disable_stage2_shutdown = false; u8 reg; WARN_ON(!mutex_is_locked(&chip->lock)); /* - * Default: S2 and S3 shutdown enabled, thresholds at + * Default: Stage 2 and Stage 3 shutdown enabled, thresholds at * lowest threshold set, monitoring at 25Hz */ reg = SHUTDOWN_CTRL1_RATE_25HZ; @@ -241,12 +244,12 @@ static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip, chip->thresh = THRESH_MAX - ((stage2_threshold_max - temp) / TEMP_THRESH_STEP); - disable_s2_shutdown = true; + disable_stage2_shutdown = true; } else { chip->thresh = THRESH_MAX; if (chip->adc) - disable_s2_shutdown = true; + disable_stage2_shutdown = true; else dev_warn(chip->dev, "No ADC is configured and critical temperature %d mC is above the maximum stage 2 threshold of %ld mC! Configuring stage 2 shutdown at %ld mC.\n", @@ -255,8 +258,8 @@ static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip, skip: reg |= chip->thresh; - if (disable_s2_shutdown) - reg |= SHUTDOWN_CTRL1_OVERRIDE_S2; + if (disable_stage2_shutdown && !chip->require_stage2_shutdown) + reg |= SHUTDOWN_CTRL1_OVERRIDE_STAGE2; return qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg); } @@ -350,8 +353,8 @@ static int qpnp_tm_probe(struct platform_device *pdev) { struct qpnp_tm_chip *chip; struct device_node *node; - u8 type, subtype, dig_major; - u32 res; + u8 type, subtype, dig_major, dig_minor; + u32 res, dig_revision; int ret, irq; node = pdev->dev.of_node; @@ -403,6 +406,11 @@ static int qpnp_tm_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, ret, "could not read dig_major\n"); + ret = qpnp_tm_read(chip, QPNP_TM_REG_DIG_MINOR, &dig_minor); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "could not read dig_minor\n"); + if (type != QPNP_TM_TYPE || (subtype != QPNP_TM_SUBTYPE_GEN1 && subtype != QPNP_TM_SUBTYPE_GEN2)) { dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n", @@ -416,6 +424,23 @@ static int qpnp_tm_probe(struct platform_device *pdev) else chip->temp_map = &temp_map_gen1; + if (chip->subtype == QPNP_TM_SUBTYPE_GEN2) { + dig_revision = (dig_major << 8) | dig_minor; + /* + * Check if stage 2 automatic partial shutdown must remain + * enabled to avoid potential repeated faults upon reaching + * over-temperature stage 3. + */ + switch (dig_revision) { + case 0x0001: + case 0x0002: + case 0x0100: + case 0x0101: + chip->require_stage2_shutdown = true; + break; + } + } + /* * Register the sensor before initializing the hardware to be able to * read the trip points. get_temp() returns the default temperature diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c index 52e26be8c53d..aed2729f63d0 100644 --- a/drivers/thermal/qoriq_thermal.c +++ b/drivers/thermal/qoriq_thermal.c @@ -18,6 +18,7 @@ #define SITES_MAX 16 #define TMR_DISABLE 0x0 #define TMR_ME 0x80000000 +#define TMR_CMD BIT(29) #define TMR_ALPF 0x0c000000 #define TMR_ALPF_V2 0x03000000 #define TMTMIR_DEFAULT 0x0000000f @@ -356,6 +357,12 @@ static int qoriq_tmu_suspend(struct device *dev) if (ret) return ret; + if (data->ver > TMU_VER1) { + ret = regmap_set_bits(data->regmap, REGS_TMR, TMR_CMD); + if (ret) + return ret; + } + clk_disable_unprepare(data->clk); return 0; @@ -370,6 +377,12 @@ static int qoriq_tmu_resume(struct device *dev) if (ret) return ret; + if (data->ver > TMU_VER1) { + ret = regmap_clear_bits(data->regmap, REGS_TMR, TMR_CMD); + if (ret) + return ret; + } + /* Enable monitoring */ return regmap_update_bits(data->regmap, REGS_TMR, TMR_ME, TMR_ME); } diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index 086ed42dd16c..a84f48a752d1 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -386,6 +386,7 @@ static const struct tsadc_table rk3328_code_table[] = { {296, -40000}, {304, -35000}, {313, -30000}, + {322, -25000}, {331, -20000}, {340, -15000}, {349, -10000}, diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 1d2f2b307bac..c2fa236e10cd 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -490,7 +490,7 @@ static void thermal_zone_device_check(struct work_struct *work) static void thermal_zone_device_init(struct thermal_zone_device *tz) { - struct thermal_instance *pos; + struct thermal_trip_desc *td; INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check); @@ -498,8 +498,12 @@ static void thermal_zone_device_init(struct thermal_zone_device *tz) tz->passive = 0; tz->prev_low_trip = -INT_MAX; tz->prev_high_trip = INT_MAX; - list_for_each_entry(pos, &tz->thermal_instances, tz_node) - pos->initialized = false; + for_each_trip_desc(tz, td) { + struct thermal_instance *instance; + + list_for_each_entry(instance, &td->thermal_instances, trip_node) + instance->initialized = false; + } } static void thermal_governor_trip_crossed(struct thermal_governor *governor, @@ -764,12 +768,12 @@ struct thermal_zone_device *thermal_zone_get_by_id(int id) * Return: 0 on success, the proper error value otherwise. */ static int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz, - const struct thermal_trip *trip, + struct thermal_trip *trip, struct thermal_cooling_device *cdev, struct cooling_spec *cool_spec) { - struct thermal_instance *dev; - struct thermal_instance *pos; + struct thermal_trip_desc *td = trip_to_trip_desc(trip); + struct thermal_instance *dev, *instance; bool upper_no_limit; int result; @@ -832,13 +836,13 @@ static int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz, goto remove_trip_file; mutex_lock(&cdev->lock); - list_for_each_entry(pos, &tz->thermal_instances, tz_node) - if (pos->trip == trip && pos->cdev == cdev) { + list_for_each_entry(instance, &td->thermal_instances, trip_node) + if (instance->cdev == cdev) { result = -EEXIST; break; } if (!result) { - list_add_tail(&dev->tz_node, &tz->thermal_instances); + list_add_tail(&dev->trip_node, &td->thermal_instances); list_add_tail(&dev->cdev_node, &cdev->thermal_instances); atomic_set(&tz->need_update, 1); @@ -872,15 +876,16 @@ free_mem: * This function is usually called in the thermal zone device .unbind callback. */ static void thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz, - const struct thermal_trip *trip, + struct thermal_trip *trip, struct thermal_cooling_device *cdev) { + struct thermal_trip_desc *td = trip_to_trip_desc(trip); struct thermal_instance *pos, *next; mutex_lock(&cdev->lock); - list_for_each_entry_safe(pos, next, &tz->thermal_instances, tz_node) { - if (pos->trip == trip && pos->cdev == cdev) { - list_del(&pos->tz_node); + list_for_each_entry_safe(pos, next, &td->thermal_instances, trip_node) { + if (pos->cdev == cdev) { + list_del(&pos->trip_node); list_del(&pos->cdev_node); thermal_governor_update_tz(tz, THERMAL_TZ_UNBIND_CDEV); @@ -1435,7 +1440,6 @@ thermal_zone_device_register_with_trips(const char *type, } } - INIT_LIST_HEAD(&tz->thermal_instances); INIT_LIST_HEAD(&tz->node); ida_init(&tz->ida); mutex_init(&tz->lock); @@ -1459,6 +1463,7 @@ thermal_zone_device_register_with_trips(const char *type, tz->num_trips = num_trips; for_each_trip_desc(tz, td) { td->trip = *trip++; + INIT_LIST_HEAD(&td->thermal_instances); /* * Mark all thresholds as invalid to start with even though * this only matters for the trips that start as invalid and diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 421522a2bb9d..163871699a60 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -30,6 +30,7 @@ struct thermal_trip_desc { struct thermal_trip trip; struct thermal_trip_attrs trip_attrs; struct list_head notify_list_node; + struct list_head thermal_instances; int notify_temp; int threshold; }; @@ -99,7 +100,6 @@ struct thermal_governor { * @tzp: thermal zone parameters * @governor: pointer to the governor for this thermal zone * @governor_data: private pointer for governor data - * @thermal_instances: list of &struct thermal_instance of this thermal zone * @ida: &struct ida to generate unique id for this zone's cooling * devices * @lock: lock to protect thermal_instances list @@ -133,7 +133,6 @@ struct thermal_zone_device { struct thermal_zone_params *tzp; struct thermal_governor *governor; void *governor_data; - struct list_head thermal_instances; struct ida ida; struct mutex lock; struct list_head node; @@ -230,7 +229,7 @@ struct thermal_instance { struct device_attribute attr; char weight_attr_name[THERMAL_NAME_LENGTH]; struct device_attribute weight_attr; - struct list_head tz_node; /* node in tz->thermal_instances */ + struct list_head trip_node; /* node in trip->thermal_instances */ struct list_head cdev_node; /* node in cdev->thermal_instances */ unsigned int weight; /* The weight of the cooling device */ bool upper_no_limit; diff --git a/drivers/thermal/thermal_helpers.c b/drivers/thermal/thermal_helpers.c index dc374a7a1a65..403d62d3ce77 100644 --- a/drivers/thermal/thermal_helpers.c +++ b/drivers/thermal/thermal_helpers.c @@ -43,10 +43,11 @@ static bool thermal_instance_present(struct thermal_zone_device *tz, struct thermal_cooling_device *cdev, const struct thermal_trip *trip) { + const struct thermal_trip_desc *td = trip_to_trip_desc(trip); struct thermal_instance *ti; - list_for_each_entry(ti, &tz->thermal_instances, tz_node) { - if (ti->trip == trip && ti->cdev == cdev) + list_for_each_entry(ti, &td->thermal_instances, trip_node) { + if (ti->cdev == cdev) return true; } diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 5d3d8ce672cd..e0aa9d9d5604 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -293,12 +293,40 @@ static bool thermal_of_get_cooling_spec(struct device_node *map_np, int index, return true; } +static bool thermal_of_cm_lookup(struct device_node *cm_np, + const struct thermal_trip *trip, + struct thermal_cooling_device *cdev, + struct cooling_spec *c) +{ + for_each_child_of_node_scoped(cm_np, child) { + struct device_node *tr_np; + int count, i; + + tr_np = of_parse_phandle(child, "trip", 0); + if (tr_np != trip->priv) + continue; + + /* The trip has been found, look up the cdev. */ + count = of_count_phandle_with_args(child, "cooling-device", + "#cooling-cells"); + if (count <= 0) + pr_err("Add a cooling_device property with at least one device\n"); + + for (i = 0; i < count; i++) { + if (thermal_of_get_cooling_spec(child, i, cdev, c)) + return true; + } + } + + return false; +} + static bool thermal_of_should_bind(struct thermal_zone_device *tz, const struct thermal_trip *trip, struct thermal_cooling_device *cdev, struct cooling_spec *c) { - struct device_node *tz_np, *cm_np, *child; + struct device_node *tz_np, *cm_np; bool result = false; tz_np = thermal_of_zone_get_by_name(tz); @@ -312,28 +340,7 @@ static bool thermal_of_should_bind(struct thermal_zone_device *tz, goto out; /* Look up the trip and the cdev in the cooling maps. */ - for_each_child_of_node(cm_np, child) { - struct device_node *tr_np; - int count, i; - - tr_np = of_parse_phandle(child, "trip", 0); - if (tr_np != trip->priv) - continue; - - /* The trip has been found, look up the cdev. */ - count = of_count_phandle_with_args(child, "cooling-device", "#cooling-cells"); - if (count <= 0) - pr_err("Add a cooling_device property with at least one device\n"); - - for (i = 0; i < count; i++) { - result = thermal_of_get_cooling_spec(child, i, cdev, c); - if (result) - break; - } - - of_node_put(child); - break; - } + result = thermal_of_cm_lookup(cm_np, trip, cdev, c); of_node_put(cm_np); out: diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c index 1838aa729bb5..c58c53d4ecc6 100644 --- a/drivers/thermal/thermal_sysfs.c +++ b/drivers/thermal/thermal_sysfs.c @@ -40,10 +40,13 @@ temp_show(struct device *dev, struct device_attribute *attr, char *buf) ret = thermal_zone_get_temp(tz, &temperature); - if (ret) - return ret; + if (!ret) + return sprintf(buf, "%d\n", temperature); - return sprintf(buf, "%d\n", temperature); + if (ret == -EAGAIN) + return -ENODATA; + + return ret; } static ssize_t |