bool bind;
};
-static struct exynos_thermal_zone *th_zone;
-
/* Get mode callback functions for thermal zone */
static int exynos_get_mode(struct thermal_zone_device *thermal,
enum thermal_device_mode *mode)
{
+ struct exynos_thermal_zone *th_zone = thermal->devdata;
if (th_zone)
*mode = th_zone->mode;
return 0;
static int exynos_set_mode(struct thermal_zone_device *thermal,
enum thermal_device_mode mode)
{
- if (!th_zone->therm_dev) {
- pr_notice("thermal zone not registered\n");
+ struct exynos_thermal_zone *th_zone = thermal->devdata;
+ if (!th_zone) {
+ dev_err(th_zone->sensor_conf->dev,
+ "thermal zone not registered\n");
return 0;
}
- mutex_lock(&th_zone->therm_dev->lock);
+ mutex_lock(&thermal->lock);
if (mode == THERMAL_DEVICE_ENABLED &&
!th_zone->sensor_conf->trip_data.trigger_falling)
- th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
+ thermal->polling_delay = IDLE_INTERVAL;
else
- th_zone->therm_dev->polling_delay = 0;
+ thermal->polling_delay = 0;
- mutex_unlock(&th_zone->therm_dev->lock);
+ mutex_unlock(&thermal->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);
+ 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 int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
enum thermal_trip_type *type)
{
- switch (GET_ZONE(trip)) {
- case MONITOR_ZONE:
- case WARN_ZONE:
- *type = THERMAL_TRIP_ACTIVE;
- break;
- case PANIC_ZONE:
+ struct exynos_thermal_zone *th_zone = thermal->devdata;
+ int max_trip = th_zone->sensor_conf->trip_data.trip_count;
+ int trip_type;
+
+ if (trip < 0 || trip >= max_trip)
+ return -EINVAL;
+
+ trip_type = th_zone->sensor_conf->trip_data.trip_type[trip];
+
+ if (trip_type == SW_TRIP)
*type = THERMAL_TRIP_CRITICAL;
- break;
- default:
+ else if (trip_type == THROTTLE_ACTIVE)
+ *type = THERMAL_TRIP_ACTIVE;
+ else if (trip_type == THROTTLE_PASSIVE)
+ *type = THERMAL_TRIP_PASSIVE;
+ else
return -EINVAL;
- }
+
return 0;
}
static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
unsigned long *temp)
{
- if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
+ struct exynos_thermal_zone *th_zone = thermal->devdata;
+ int max_trip = th_zone->sensor_conf->trip_data.trip_count;
+
+ if (trip < 0 || trip >= max_trip)
return -EINVAL;
*temp = th_zone->sensor_conf->trip_data.trip_val[trip];
static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
unsigned long *temp)
{
- int ret;
- /* Panic zone */
- ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
- return ret;
+ struct exynos_thermal_zone *th_zone = thermal->devdata;
+ int max_trip = th_zone->sensor_conf->trip_data.trip_count;
+ /* Get the temp of highest trip*/
+ return exynos_get_trip_temp(thermal, max_trip - 1, temp);
}
/* Bind callback functions for thermal zone */
{
int ret = 0, i, tab_size, level;
struct freq_clip_table *tab_ptr, *clip_data;
+ struct exynos_thermal_zone *th_zone = thermal->devdata;
struct thermal_sensor_conf *data = th_zone->sensor_conf;
tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
tab_size = data->cooling_data.freq_clip_count;
if (tab_ptr == NULL || tab_size == 0)
- return -EINVAL;
+ return 0;
/* find the cooling device registered*/
for (i = 0; i < th_zone->cool_dev_size; i++)
case WARN_ZONE:
if (thermal_zone_bind_cooling_device(thermal, i, cdev,
level, 0)) {
- pr_err("error binding cdev inst %d\n", i);
+ dev_err(data->dev,
+ "error unbinding cdev inst=%d\n", i);
ret = -EINVAL;
}
th_zone->bind = true;
struct thermal_cooling_device *cdev)
{
int ret = 0, i, tab_size;
+ struct exynos_thermal_zone *th_zone = thermal->devdata;
struct thermal_sensor_conf *data = th_zone->sensor_conf;
if (th_zone->bind == false)
tab_size = data->cooling_data.freq_clip_count;
if (tab_size == 0)
- return -EINVAL;
+ return 0;
/* find the cooling device registered*/
for (i = 0; i < th_zone->cool_dev_size; i++)
case WARN_ZONE:
if (thermal_zone_unbind_cooling_device(thermal, i,
cdev)) {
- pr_err("error unbinding cdev inst=%d\n", i);
+ dev_err(data->dev,
+ "error unbinding cdev inst=%d\n", i);
ret = -EINVAL;
}
th_zone->bind = false;
static int exynos_get_temp(struct thermal_zone_device *thermal,
unsigned long *temp)
{
+ struct exynos_thermal_zone *th_zone = thermal->devdata;
void *data;
if (!th_zone->sensor_conf) {
- pr_info("Temperature sensor not initialised\n");
+ dev_err(th_zone->sensor_conf->dev,
+ "Temperature sensor not initialised\n");
return -EINVAL;
}
- data = th_zone->sensor_conf->private_data;
+ data = th_zone->sensor_conf->driver_data;
*temp = th_zone->sensor_conf->read_temperature(data);
/* convert the temperature into millicelsius */
*temp = *temp * MCELSIUS;
{
void *data;
int ret = -EINVAL;
+ struct exynos_thermal_zone *th_zone = thermal->devdata;
if (!th_zone->sensor_conf) {
- pr_info("Temperature sensor not initialised\n");
+ dev_err(th_zone->sensor_conf->dev,
+ "Temperature sensor not initialised\n");
return -EINVAL;
}
- data = th_zone->sensor_conf->private_data;
+ data = th_zone->sensor_conf->driver_data;
if (th_zone->sensor_conf->write_emul_temp)
ret = th_zone->sensor_conf->write_emul_temp(data, temp);
return ret;
* This function may be called from interrupt based temperature sensor
* when threshold is changed.
*/
-void exynos_report_trigger(void)
+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 (!th_zone || !th_zone->therm_dev)
+ 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])
{
int ret;
struct cpumask mask_val;
+ struct exynos_thermal_zone *th_zone;
if (!sensor_conf || !sensor_conf->read_temperature) {
pr_err("Temperature sensor not initialised\n");
return -EINVAL;
}
- th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
+ th_zone = devm_kzalloc(sensor_conf->dev,
+ sizeof(struct exynos_thermal_zone), GFP_KERNEL);
if (!th_zone)
return -ENOMEM;
th_zone->sensor_conf = sensor_conf;
- cpumask_set_cpu(0, &mask_val);
- th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
- if (IS_ERR(th_zone->cool_dev[0])) {
- pr_err("Failed to register cpufreq cooling device\n");
- ret = -EINVAL;
- goto err_unregister;
+ /*
+ * TODO: 1) Handle multiple cooling devices in a thermal zone
+ * 2) Add a flag/name in cooling info to map to specific
+ * sensor
+ */
+ if (sensor_conf->cooling_data.freq_clip_count > 0) {
+ cpumask_set_cpu(0, &mask_val);
+ th_zone->cool_dev[th_zone->cool_dev_size] =
+ cpufreq_cooling_register(&mask_val);
+ if (IS_ERR(th_zone->cool_dev[th_zone->cool_dev_size])) {
+ dev_err(sensor_conf->dev,
+ "Failed to register cpufreq cooling device\n");
+ ret = -EINVAL;
+ goto err_unregister;
+ }
+ th_zone->cool_dev_size++;
}
- th_zone->cool_dev_size++;
- th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
- EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
- sensor_conf->trip_data.trigger_falling ?
- 0 : IDLE_INTERVAL);
+ th_zone->therm_dev = thermal_zone_device_register(
+ sensor_conf->name, sensor_conf->trip_data.trip_count,
+ 0, th_zone, &exynos_dev_ops, NULL, 0,
+ sensor_conf->trip_data.trigger_falling ? 0 :
+ IDLE_INTERVAL);
if (IS_ERR(th_zone->therm_dev)) {
- pr_err("Failed to register thermal zone device\n");
+ dev_err(sensor_conf->dev,
+ "Failed to register thermal zone device\n");
ret = PTR_ERR(th_zone->therm_dev);
goto err_unregister;
}
th_zone->mode = THERMAL_DEVICE_ENABLED;
+ sensor_conf->pzone_data = th_zone;
- pr_info("Exynos: Kernel Thermal management registered\n");
+ dev_info(sensor_conf->dev,
+ "Exynos: Thermal zone(%s) registered\n", sensor_conf->name);
return 0;
err_unregister:
- exynos_unregister_thermal();
+ exynos_unregister_thermal(sensor_conf);
return ret;
}
/* Un-Register with the in-kernel thermal management */
-void exynos_unregister_thermal(void)
+void exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf)
{
int i;
+ struct exynos_thermal_zone *th_zone;
- if (!th_zone)
+ if (!sensor_conf || !sensor_conf->pzone_data) {
+ pr_err("Invalid temperature sensor configuration data\n");
return;
+ }
+
+ th_zone = sensor_conf->pzone_data;
if (th_zone->therm_dev)
thermal_zone_device_unregister(th_zone->therm_dev);
cpufreq_cooling_unregister(th_zone->cool_dev[i]);
}
- kfree(th_zone);
- pr_info("Exynos: Kernel Thermal management unregistered\n");
+ dev_info(sensor_conf->dev,
+ "Exynos: Kernel Thermal management unregistered\n");
}