/* * 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); }
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, ®); 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; }
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); }
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; }
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; }
/* 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; }
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; }
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; }
static void acpi_thermal_check(void *data) { struct acpi_thermal *tz = data; if (!tz->tz_enabled) return; thermal_zone_device_update(tz->thermal_zone); }
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); }
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); }
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; }
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; }
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)); }
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; }
/*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; }
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; }
/* * 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); }
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"); }
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; }
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; }
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; }
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; }
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, ®, 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; }
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; }
/* 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); }