Пример #1
0
/*
 * This function may be called from interrupt based temperature sensor
 * when threshold is changed.
 */
static void exynos_report_trigger(void)
{
	unsigned int i;
	char data[10];
	char *envp[] = { data, NULL };

	if (!th_zone || !th_zone->therm_dev)
		return;

	thermal_zone_device_update(th_zone->therm_dev);

	mutex_lock(&th_zone->therm_dev->lock);
	/* Find the level for which trip happened */
	for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
		if (th_zone->therm_dev->last_temperature <
			th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
			break;
	}

	if (th_zone->mode == THERMAL_DEVICE_ENABLED) {
		if (i > 0)
			th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
		else
			th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
	}

	snprintf(data, sizeof(data), "%u", i);
	kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
	mutex_unlock(&th_zone->therm_dev->lock);
}
Пример #2
0
static irqreturn_t pm8901_tm_isr(int irq, void *data)
{
	struct pm8901_tm_device *tm = data;
	int rc;
	u8 reg;

	rc = pm8901_tm_update_temp(tm);
	if (rc < 0)
		goto isr_handled;

	rc = pm8901_tm_read_ctrl(tm->pm_chip, &reg);
	if (rc < 0)
		goto isr_handled;

	pr_info("%s: Temp Alarm - stage=%u, threshold=%u, temp=%lu\n",
		__func__, tm->stage, tm->thresh, tm->temp);

	if (reg & (PM8901_TEMP_ST2_SD | PM8901_TEMP_ST3_SD)) {
		reg &= ~(PM8901_TEMP_ST2_SD | PM8901_TEMP_ST3_SD |
			 PM8901_TEMP_STATUS_MASK);

		pm8901_tm_write_ctrl(tm->pm_chip, reg);
	}

	thermal_zone_device_update(tm->tz_dev);

	/* Notify user space */
	if (tm->mode == THERMAL_DEVICE_ENABLED)
		kobject_uevent(&tm->tz_dev->device.kobj, KOBJ_CHANGE);

isr_handled:
	return IRQ_HANDLED;
}
/* Set mode callback functions for thermal zone */
static int exynos_set_mode(struct thermal_zone_device *thermal,
			enum thermal_device_mode mode)
{
	struct exynos_thermal_zone *th_zone = thermal->devdata;
	if (!th_zone) {
		dev_err(&thermal->device,
			"thermal zone not registered\n");
		return 0;
	}

	mutex_lock(&thermal->lock);

	if (mode == THERMAL_DEVICE_ENABLED &&
		!th_zone->sensor_conf->trip_data.trigger_falling)
		thermal->polling_delay = IDLE_INTERVAL;
	else
		thermal->polling_delay = 0;

	mutex_unlock(&thermal->lock);

	th_zone->mode = mode;
	thermal_zone_device_update(thermal);
	dev_dbg(th_zone->sensor_conf->dev,
		"thermal polling set for duration=%d msec\n",
		thermal->polling_delay);
	return 0;
}
Пример #4
0
static ssize_t mtktspmic_write(struct file *file, const char *buffer, unsigned long count, void *data)
{
    int len=0,time_msec=0;
    char desc[32];
    
    len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
    if (copy_from_user(desc, buffer, len))
    {
        return 0;
    }
    desc[len] = '\0';
    
    if (sscanf(desc, "%d",&time_msec) == 1)
    {
        interval=time_msec / 1000;
        thz_dev->polling_delay = interval*1000;
	    thermal_zone_device_update(thz_dev);
        
        mtktspmic_dprintk("[mtktspmic_write] time_ms=%d\n", interval*1000);
        
        return count;
    }
    else
    {
        mtktspmic_dprintk("[mtktspmic_write] bad argument\n");
    }
    
    return -EINVAL;
}
static void kona_tmon_irq_work(struct work_struct *work)
{
	struct kona_tmon_thermal *thermal = container_of(work,
					struct kona_tmon_thermal, isr_work);
	struct kona_tmon_pdata *pdata = thermal->pdata;
	unsigned long cur_temp;

	mutex_lock(&thermal->lock);
	cur_temp = kona_tmon_get_current_temp(thermal->pdata, true, true);
	/* Interrupt is triggered twice sometimes. As an workaround,
	 * check if current temp is less than the threshold value */
	if (cur_temp < pdata->trips[thermal->cur_idx].temp)
		goto out;

	tmon_dbg(TMON_LOG_ALERT, "soc threshold (%d)C exceeded, cur temp is %ldC\n",
				pdata->trips[thermal->cur_idx].temp, cur_temp);

	/* Set threshold to next level */
	cancel_delayed_work_sync(&thermal->polling_work);

	if (thermal->cur_idx < thermal->active_cnt - 1)
		thermal->cur_idx++;

	kona_tmon_set_theshold(pdata,
			pdata->trips[thermal->cur_idx].temp);

	thermal_zone_device_update(thermal->tz);

	schedule_delayed_work(&thermal->polling_work,
			msecs_to_jiffies(pdata->poll_rate_ms));
out:
	mutex_unlock(&thermal->lock);
}
Пример #6
0
static int imx_set_mode(struct thermal_zone_device *tz,
			enum thermal_device_mode mode)
{
	struct imx_thermal_data *data = tz->devdata;
	struct regmap *map = data->tempmon;

	if (mode == THERMAL_DEVICE_ENABLED) {
		tz->polling_delay = IMX_POLLING_DELAY;
		tz->passive_delay = IMX_PASSIVE_DELAY;

		regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
		regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);

		if (!data->irq_enabled) {
			data->irq_enabled = true;
			enable_irq(data->irq);
		}
	} else {
		regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
		regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);

		tz->polling_delay = 0;
		tz->passive_delay = 0;

		if (data->irq_enabled) {
			disable_irq(data->irq);
			data->irq_enabled = false;
		}
	}

	data->mode = mode;
	thermal_zone_device_update(tz);

	return 0;
}
Пример #7
0
static int anatop_thermal_set_mode(struct thermal_zone_device *thermal,
				enum thermal_device_mode mode)
{
	struct anatop_thermal *tz = thermal->devdata;
	int enable;

	if (!tz)
		return -EINVAL;

	/* enable/disable thermal management from thermal driver */
	if (mode == THERMAL_DEVICE_ENABLED)
		enable = 1;
	else if (mode == THERMAL_DEVICE_DISABLED)
		enable = 0;
	else
		return -EINVAL;

	if (enable != tz->tz_enabled) {
		tz->tz_enabled = enable;
		printk(KERN_INFO "%s anatop thermal control\n",
			tz->tz_enabled ? enabled : disabled);
		thermal_zone_device_update(tz->thermal_zone);
	}
	return 0;
}
Пример #8
0
/* Set mode callback functions for thermal zone */
static int exynos_set_mode(struct thermal_zone_device *thermal,
			enum thermal_device_mode mode)
{
	bool on;
	int i;

	if (!th_zone->therm_dev) {
		pr_notice("thermal zone not registered\n");
		return 0;
	}

	mutex_lock(&th_zone->therm_dev->lock);

	if (mode == THERMAL_DEVICE_ENABLED) {
		th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
		on = true;
	} else {
		th_zone->therm_dev->polling_delay = 0;
		on = false;
	}

	for (i = 0; i < EXYNOS_TMU_COUNT; i++)
		exynos_tmu_control(th_zone->exynos4_dev, i, on);

	mutex_unlock(&th_zone->therm_dev->lock);

	th_zone->mode = mode;
	thermal_zone_device_update(th_zone->therm_dev);
	pr_info("thermal polling set for duration=%d msec\n",
				th_zone->therm_dev->polling_delay);
	return 0;
}
Пример #9
0
static irqreturn_t uniphier_tm_alarm_irq_thread(int irq, void *_tdev)
{
	struct uniphier_tm_dev *tdev = _tdev;

	thermal_zone_device_update(tdev->tz_dev, THERMAL_EVENT_UNSPECIFIED);

	return IRQ_HANDLED;
}
Пример #10
0
static irqreturn_t max8973_thermal_irq(int irq, void *data)
{
	struct max8973_chip *mchip = data;

	thermal_zone_device_update(mchip->tz_device);

	return IRQ_HANDLED;
}
Пример #11
0
static void acpi_thermal_check(void *data)
{
	struct acpi_thermal *tz = data;

	if (!tz->tz_enabled)
		return;

	thermal_zone_device_update(tz->thermal_zone);
}
Пример #12
0
static void tz_device_update_work_fn(struct work_struct *work)
{
	struct tegra_bpmp_thermal_zone *zone;

	zone = container_of(work, struct tegra_bpmp_thermal_zone,
			    tz_device_update_work);

	thermal_zone_device_update(zone->tzd, THERMAL_TRIP_VIOLATED);
}
Пример #13
0
static void acpi_thermal_check(void *data)
{
    struct acpi_thermal *tz = data;

    if (!tz->tz_enabled)
        return;

    thermal_zone_device_update(tz->thermal_zone,
                               THERMAL_EVENT_UNSPECIFIED);
}
Пример #14
0
static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
{
	struct imx_thermal_data *data = dev;

	dev_dbg(&data->tz->device, "THERMAL ALARM: T > %lu\n",
		data->alarm_temp / 1000);

	thermal_zone_device_update(data->tz);

	return IRQ_HANDLED;
}
Пример #15
0
static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
{
	struct rockchip_thermal_data *thermal = dev;
	int i;

	dev_dbg(&thermal->pdev->dev, "thermal alarm\n");

	thermal->chip->irq_ack(thermal->regs);

	for (i = 0; i < ARRAY_SIZE(thermal->sensors); i++)
		thermal_zone_device_update(thermal->sensors[i].tzd);

	return IRQ_HANDLED;
}
Пример #16
0
static void therm_fan_est_work_func(struct work_struct *work)
{
	int i, j, index, trip_index, sum = 0;
	long temp = 0;
	struct delayed_work *dwork = container_of(work,
					struct delayed_work, work);
	struct therm_fan_estimator *est = container_of(
					dwork,
					struct therm_fan_estimator,
					therm_fan_est_work);

	for (i = 0; i < est->ndevs; i++) {
		if (est->devs[i].get_temp(est->devs[i].dev_data, &temp))
			continue;
		est->devs[i].hist[(est->ntemp % HIST_LEN)] = temp;
	}

	for (i = 0; i < est->ndevs; i++) {
		for (j = 0; j < HIST_LEN; j++) {
			index = (est->ntemp - j + HIST_LEN) % HIST_LEN;
			sum += est->devs[i].hist[index] *
				est->devs[i].coeffs[j];
		}
	}
#if !DEBUG
	est->cur_temp = sum / 100 + est->toffset;
#else
	est->cur_temp = est->cur_temp_debug;
#endif
	for (trip_index = 0;
		trip_index < ((MAX_ACTIVE_STATES << 1) + 1); trip_index++) {
		if (est->cur_temp < est->active_trip_temps_hyst[trip_index])
			break;
	}
	if (est->current_trip_index != (trip_index - 1)) {
		if (!((trip_index - 1) % 2) || (!est->current_trip_index) ||
			((trip_index - est->current_trip_index) >= 2) ||
			((trip_index - est->current_trip_index) <= -2)) {
			pr_info("%s, cur_temp:%ld, cur_trip_index:%d",
			__func__, est->cur_temp, est->current_trip_index);
			thermal_zone_device_update(est->thz);
		}
		est->current_trip_index = trip_index - 1;
	}

	est->ntemp++;
	queue_delayed_work(est->workqueue, &est->therm_fan_est_work,
				msecs_to_jiffies(est->polling_period));
}
Пример #17
0
static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
{
	struct rockchip_thermal_data *thermal = dev;
	int i;

	dev_dbg(&thermal->pdev->dev, "thermal alarm\n");

	thermal->chip->irq_ack(thermal->regs);

	for (i = 0; i < thermal->chip->chn_num; i++)
		thermal_zone_device_update(thermal->sensors[i].tzd,
					   THERMAL_EVENT_UNSPECIFIED);

	return IRQ_HANDLED;
}
Пример #18
0
/*This may be called from interrupt based temperature sensor*/
void exynos4_report_trigger(void)
{
	unsigned int th_temp = th_zone->sensor_data->threshold;
	unsigned int monitor_temp = th_temp +
			th_zone->sensor_data->trigger_levels[1];

	thermal_zone_device_update(th_zone->therm_dev);

	if (th_zone->therm_dev->last_temperature > monitor_temp)
		th_zone->therm_dev->polling_delay =
					th_zone->active_interval*1000;
	else
		th_zone->therm_dev->polling_delay =
					th_zone->idle_interval*1000;
}
Пример #19
0
static irqreturn_t rcar_gen3_thermal_irq_thread(int irq, void *data)
{
	struct rcar_gen3_thermal_priv *priv = data;
	unsigned long flags;
	int i;

	for (i = 0; i < priv->num_tscs; i++)
		thermal_zone_device_update(priv->tscs[i]->zone,
					   THERMAL_EVENT_UNSPECIFIED);

	spin_lock_irqsave(&priv->lock, flags);
	rcar_thermal_irq_set(priv, true);
	spin_unlock_irqrestore(&priv->lock, flags);

	return IRQ_HANDLED;
}
Пример #20
0
/*
 * This function may be called from interrupt based temperature sensor
 * when threshold is changed.
 */
void exynos_report_trigger(struct thermal_sensor_conf *conf)
{
    unsigned int i;
    char data[10];
    char *envp[] = { data, NULL };
    struct exynos_thermal_zone *th_zone;

    if (!conf || !conf->pzone_data) {
        pr_err("Invalid temperature sensor configuration data\n");
        return;
    }

    th_zone = conf->pzone_data;
    if (th_zone->therm_dev)
        return;

    if (th_zone->bind == false) {
        for (i = 0; i < th_zone->cool_dev_size; i++) {
            if (!th_zone->cool_dev[i])
                continue;
            exynos_bind(th_zone->therm_dev,
                        th_zone->cool_dev[i]);
        }
    }

    thermal_zone_device_update(th_zone->therm_dev);

    mutex_lock(&th_zone->therm_dev->lock);
    /* Find the level for which trip happened */
    for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
        if (th_zone->therm_dev->last_temperature <
                th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
            break;
    }

    if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
            !th_zone->sensor_conf->trip_data.trigger_falling) {
        if (i > 0)
            th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
        else
            th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
    }

    snprintf(data, sizeof(data), "%u", i);
    kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
    mutex_unlock(&th_zone->therm_dev->lock);
}
Пример #21
0
static void db8500_thermal_work(struct work_struct *work)
{
	enum thermal_device_mode cur_mode;
	struct db8500_thermal_zone *pzone;

	pzone = container_of(work, struct db8500_thermal_zone, therm_work);

	mutex_lock(&pzone->th_lock);
	cur_mode = pzone->mode;
	mutex_unlock(&pzone->th_lock);

	if (cur_mode == THERMAL_DEVICE_DISABLED)
		return;

	thermal_zone_device_update(pzone->therm_dev);
	dev_dbg(&pzone->therm_dev->device, "thermal work finished.\n");
}
Пример #22
0
static void therm_est_work_func(struct work_struct *work)
{
	int i, j, index, sum = 0;
	long temp;
	struct delayed_work *dwork = container_of(work,
					struct delayed_work, work);
	struct therm_estimator *est = container_of(dwork,
					struct therm_estimator,
					therm_est_work);

	if ((est->ntemp == HIST_UNINIT) && therm_est_init_history(est)) {
		est->cur_temp = DEFAULT_TEMP;
		goto out;
	}

	for (i = 0; i < est->ndevs; i++) {
		if (therm_est_subdev_get_temp(est->devs[i].dev_data, &temp)) {
			index = (est->ntemp > 0) ? (est->ntemp - 1) : 0;
			temp = est->devs[i].hist[(index % HIST_LEN)];
		}
		est->devs[i].hist[(est->ntemp % HIST_LEN)] = temp;
	}

	for (i = 0; i < est->ndevs; i++) {
		for (j = 0; j < HIST_LEN; j++) {
			index = (est->ntemp - j + HIST_LEN) % HIST_LEN;
			sum += est->devs[i].hist[index] *
				est->devs[i].coeffs[j];
		}
	}

	est->cur_temp = sum / 100 + est->toffset;
	est->ntemp++;

out:
	if (est->thz && ((est->cur_temp < est->low_limit) ||
			(est->cur_temp >= est->high_limit))) {
		thermal_zone_device_update(est->thz);
		therm_est_update_timer_trips(est);
		therm_est_update_limits(est);
	}

	queue_delayed_work(est->workqueue, &est->therm_est_work,
				msecs_to_jiffies(est->polling_period));
}
/* Set mode callback functions for thermal zone */
static int amlogic_set_mode(struct thermal_zone_device *thermal,
        enum thermal_device_mode mode)
{
    struct  amlogic_thermal_platform_data *pdata= thermal->devdata;
    struct cpucore_cooling_device *cpucore_device =NULL;
    struct gpucore_cooling_device *gpucore_device = NULL;
    if(!pdata)
        return -EINVAL;

    //mutex_lock(&pdata->therm_dev->lock);

    if (mode == THERMAL_DEVICE_ENABLED){
        pdata->therm_dev->polling_delay = pdata->idle_interval;
        if(pdata->cpucore_cool_dev){
            cpucore_device=pdata->cpucore_cool_dev->devdata;
            cpucore_device->stop_flag=0;
        }
        if(pdata->gpucore_cool_dev){
            gpucore_device=pdata->gpucore_cool_dev->devdata;
            gpucore_device->stop_flag=0;
        }
        if (pdata->keep_mode) {                     // start work
            schedule_delayed_work(&pdata->thermal_work, msecs_to_jiffies(100));
        }
    }
    else{
        pdata->therm_dev->polling_delay = 0;
        if (pdata->keep_mode) {
            cancel_delayed_work_sync(&pdata->thermal_work);
            keep_mode_set_mode(pdata);
        }
        if(pdata->cpucore_cool_dev)
            pdata->cpucore_cool_dev->ops->set_cur_state(pdata->cpucore_cool_dev,(0|CPU_STOP));
        if(pdata->gpucore_cool_dev)
            pdata->gpucore_cool_dev->ops->set_cur_state(pdata->gpucore_cool_dev,(0|GPU_STOP));
    }

    //mutex_unlock(&pdata->therm_dev->lock);

    pdata->mode = mode;
    thermal_zone_device_update(pdata->therm_dev);
    THERMAL_INFO("thermal polling set for duration=%d msec\n",
            pdata->therm_dev->polling_delay);
    return 0;
}
Пример #24
0
static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev)
{
	struct hisi_thermal_data *data = dev;
	struct hisi_thermal_sensor *sensor;
	int i;

	mutex_lock(&data->thermal_lock);
	sensor = &data->sensors[data->irq_bind_sensor];

	dev_crit(&data->pdev->dev, "THERMAL ALARM: T > %d\n",
		 sensor->thres_temp / 1000);
	mutex_unlock(&data->thermal_lock);

	for (i = 0; i < HISI_MAX_SENSORS; i++)
		thermal_zone_device_update(data->sensors[i].tzd);

	return IRQ_HANDLED;
}
Пример #25
0
static int exynos4_set_mode(struct thermal_zone_device *thermal,
			    enum thermal_device_mode mode)
{
	if (!th_zone->therm_dev) {
		pr_notice("thermal zone not registered\n");
		return 0;
	}
	if (mode == THERMAL_DEVICE_ENABLED)
		th_zone->therm_dev->polling_delay =
				th_zone->active_interval*1000;
	else
		th_zone->therm_dev->polling_delay =
				th_zone->idle_interval*1000;

	thermal_zone_device_update(th_zone->therm_dev);
	pr_info("thermal polling set for duration=%d sec\n",
				th_zone->therm_dev->polling_delay/1000);
	return 0;
}
Пример #26
0
static int of_thermal_set_mode(struct thermal_zone_device *tz,
			       enum thermal_device_mode mode)
{
	struct __thermal_zone *data = tz->devdata;

	mutex_lock(&tz->lock);

	if (mode == THERMAL_DEVICE_ENABLED)
		tz->polling_delay = data->polling_delay;
	else
		tz->polling_delay = 0;

	mutex_unlock(&tz->lock);

	data->mode = mode;
	thermal_zone_device_update(tz);

	return 0;
}
Пример #27
0
static void qpnp_tm_work(struct work_struct *work)
{
	struct delayed_work *dwork
		= container_of(work, struct delayed_work, work);
	struct qpnp_tm_chip *chip
		= container_of(dwork, struct qpnp_tm_chip, irq_work);
	int rc;
	u8 reg;

	if (chip->adc_type == QPNP_TM_ADC_NONE) {
		rc = qpnp_tm_update_temp_no_adc(chip);
		if (rc < 0)
			goto bail;
	} else {
		rc = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, &reg, 1);
		if (rc < 0)
			goto bail;

		chip->stage = reg & STATUS_STAGE_MASK;

		rc = qpnp_tm_update_temp(chip);
		if (rc < 0)
			goto bail;
	}

	if (chip->stage != chip->prev_stage) {
		chip->prev_stage = chip->stage;

		pr_crit("%s: PMIC Temp Alarm - stage=%u, threshold=%u, temperature=%lu mC\n",
			chip->tm_name, chip->stage, chip->thresh,
			chip->temperature);

		thermal_zone_device_update(chip->tz_dev);

		/* Notify user space */
		sysfs_notify(&chip->tz_dev->device.kobj, NULL, "type");
	}

bail:
	return;
}
Пример #28
0
static int of_thermal_set_mode(struct thermal_zone_device *tz,
			       enum thermal_device_mode mode)
{
	struct __thermal_zone *data = tz->devdata;

	mutex_lock(&tz->lock);

	if (mode == THERMAL_DEVICE_ENABLED) {
		tz->polling_delay = data->polling_delay;
		tz->passive_delay = data->passive_delay;
	} else {
		tz->polling_delay = 0;
		tz->passive_delay = 0;
	}

	mutex_unlock(&tz->lock);

	data->mode = mode;
	thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);

	return 0;
}
Пример #29
0
/* Set mode callback functions for thermal zone */
static int exynos4_set_mode(struct thermal_zone_device *thermal,
			enum thermal_device_mode mode)
{
	if (!th_zone->therm_dev) {
		pr_notice("thermal zone not registered\n");
		return 0;
	}

	mutex_lock(&th_zone->therm_dev->lock);

	if (mode == THERMAL_DEVICE_ENABLED)
		th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
	else
		th_zone->therm_dev->polling_delay = 0;

	mutex_unlock(&th_zone->therm_dev->lock);

	th_zone->mode = mode;
	thermal_zone_device_update(th_zone->therm_dev);
	pr_info("thermal polling set for duration=%d msec\n",
				th_zone->therm_dev->polling_delay);
	return 0;
}
static void kona_tmon_polling_work(struct work_struct *work)
{
	struct kona_tmon_thermal *thermal = container_of(
			(struct delayed_work *)work,
			struct kona_tmon_thermal, polling_work);
	struct kona_tmon_pdata *pdata = thermal->pdata;
	unsigned long cur_temp, falling_temp;
	int idx, tz_update = 0;

	mutex_lock(&thermal->lock);
	cur_temp = kona_tmon_get_current_temp(pdata, true, true);
	/* check how far current temp is down wrt to current theshold */
	for (idx = thermal->cur_idx; idx >= 0 && thermal->cur_idx; idx--) {
		falling_temp = pdata->trips[thermal->cur_idx-1].temp -
			pdata->falling + pdata->hysteresis;

		if (cur_temp <= falling_temp) {
			tmon_dbg(TMON_LOG_ALERT, "soc temp is below thold (%d)C, cur temp is %ldC\n",
				pdata->trips[thermal->cur_idx].temp, cur_temp);
			thermal->cur_idx--;
			tz_update++;
		} else {
			break;
		}
	}

	if (tz_update) {
		kona_tmon_set_theshold(pdata,
				pdata->trips[thermal->cur_idx].temp);
		thermal_zone_device_update(thermal->tz);
	}

	if (thermal->cur_idx)
		schedule_delayed_work(&thermal->polling_work,
				msecs_to_jiffies(pdata->poll_rate_ms));
	mutex_unlock(&thermal->lock);
}