summaryrefslogtreecommitdiff
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorJoshua Primero <jprimero@nvidia.com>2012-08-29 19:18:59 -0700
committerSimone Willett <swillett@nvidia.com>2012-10-25 15:48:15 -0700
commitad82083085a6dafe25a67e31186fc3e33a643d35 (patch)
tree4400e4c8b9e8dea6d689fde6f664d5df5c23f730 /drivers/hwmon
parenta81fe0e98b9d23dac649f43c71bc2cbc8bba8bae (diff)
drivers: hwmon: tsensor: decoupled tsensor driver
Removed outside interface of tsensor driver. Tsensor driver interacts with cooling devices via Linux thermal framework which it registers to on its own. Change-Id: I349761a28eac94f7f6c05d192394bc2739e93cb6 Signed-off-by: Joshua Primero <jprimero@nvidia.com> Reviewed-on: http://git-master/r/132882 (cherry picked from commit 6645d1062b2d76a504ef7a109b919d631169f479) Signed-off-by: Gaurav Batra <gbatra@nvidia.com> Reviewed-on: http://git-master/r/130288 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com> Tested-by: Diwakar Tundlam <dtundlam@nvidia.com>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/tegra-tsensor.c174
1 files changed, 135 insertions, 39 deletions
diff --git a/drivers/hwmon/tegra-tsensor.c b/drivers/hwmon/tegra-tsensor.c
index 92e5e8b43d0b..031ea67dbff6 100644
--- a/drivers/hwmon/tegra-tsensor.c
+++ b/drivers/hwmon/tegra-tsensor.c
@@ -1,7 +1,7 @@
/*
* NVIDIA Tegra SOC - temperature sensor driver
*
- * Copyright (C) 2011 NVIDIA Corporation
+ * Copyright (C) 2011-2012 NVIDIA Corporation
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -172,6 +172,7 @@ enum tsensor_thresholds {
* The structure is dynamically allocated.
*/
struct tegra_tsensor_data {
+ struct tegra_tsensor_platform_data plat_data;
struct delayed_work work;
struct workqueue_struct *workqueue;
struct mutex mutex;
@@ -211,9 +212,7 @@ struct tegra_tsensor_data {
long current_lo_limit;
bool is_edp_supported;
-
- void (*alert_func)(void *);
- void *alert_data;
+ struct thermal_zone_device *thz;
};
enum {
@@ -651,14 +650,6 @@ static struct sensor_device_attribute tsensor_nodes[] = {
tsensor_show_limits, NULL, TSENSOR_LIMITS),
};
-int tsensor_thermal_get_temp_low(struct tegra_tsensor_data *data,
- long *milli_temp)
-{
- /* temp to counter below 20C seems to be inaccurate */
- *milli_temp = 0;
- return 0;
-}
-
int tsensor_thermal_get_temp(struct tegra_tsensor_data *data,
long *milli_temp)
{
@@ -1572,7 +1563,15 @@ static void tsensor_set_limits(
tsensor_writel(data, config, ((data->instance << 16) | offset));
}
-int tsensor_thermal_set_limits(struct tegra_tsensor_data *data,
+static int tsensor_within_limits(struct tegra_tsensor_data *data)
+{
+ int ts_state = get_ts_state(data);
+
+ return (ts_state == TS_LEVEL1);
+}
+
+#ifdef CONFIG_THERMAL
+static int tsensor_thermal_set_limits(struct tegra_tsensor_data *data,
long lo_limit_milli,
long hi_limit_milli)
{
@@ -1615,46 +1614,45 @@ done:
return 0;
}
-int tsensor_thermal_set_alert(struct tegra_tsensor_data *data,
- void (*alert_func)(void *),
- void *alert_data)
+static void tsensor_update(struct tegra_tsensor_data *data)
{
- mutex_lock(&data->mutex);
+ struct thermal_zone_device *thz = data->thz;
+ long temp, trip_temp, low_temp = 0, high_temp = 120000;
+ int count;
- data->alert_data = alert_data;
- data->alert_func = alert_func;
+ if (!thz)
+ return;
- mutex_unlock(&data->mutex);
+ if (!thz->passive)
+ thermal_zone_device_update(thz);
- return 0;
-}
+ thz->ops->get_temp(thz, &temp);
-int tsensor_thermal_set_shutdown_temp(struct tegra_tsensor_data *data,
- long shutdown_temp_milli)
-{
- long shutdown_temp = MILLICELSIUS_TO_CELSIUS(shutdown_temp_milli);
- tsensor_set_limits(data, shutdown_temp, TSENSOR_TH3);
+ for (count = 0; count < thz->trips; count++) {
+ thz->ops->get_trip_temp(thz, count, &trip_temp);
- return 0;
-}
+ if ((trip_temp >= temp) && (trip_temp < high_temp))
+ high_temp = trip_temp;
-static int tsensor_within_limits(struct tegra_tsensor_data *data)
-{
- int ts_state = get_ts_state(data);
+ if ((trip_temp < temp) && (trip_temp > low_temp))
+ low_temp = trip_temp;
+ }
- return (ts_state == TS_LEVEL1);
+ tsensor_thermal_set_limits(data, low_temp, high_temp);
+}
+#else
+static void tsensor_update(struct tegra_tsensor_data *data)
+{
}
+#endif
static void tsensor_work_func(struct work_struct *work)
{
struct tegra_tsensor_data *data = container_of(to_delayed_work(work),
struct tegra_tsensor_data, work);
- if (!data->alert_func)
- return;
-
if (!tsensor_within_limits(data)) {
- data->alert_func(data->alert_data);
+ tsensor_update(data);
if (!tsensor_within_limits(data))
dev_dbg(data->hwmon_dev,
@@ -1789,6 +1787,77 @@ fail:
return err;
}
+#ifdef CONFIG_THERMAL
+static int tsensor_get_temp(struct thermal_zone_device *thz,
+ unsigned long *temp)
+{
+ struct tegra_tsensor_data *data = thz->devdata;
+ return tsensor_thermal_get_temp(data, temp);
+}
+
+static int tsensor_bind(struct thermal_zone_device *thz,
+ struct thermal_cooling_device *cdev)
+{
+ int i;
+ struct tegra_tsensor_data *data = thz->devdata;
+
+ if (cdev == data->plat_data.passive.cdev)
+ return thermal_zone_bind_cooling_device(thz, 0, cdev);
+
+ for (i = 0; data->plat_data.active[i].cdev; i++)
+ if (cdev == data->plat_data.active[i].cdev)
+ return thermal_zone_bind_cooling_device(thz, i+1, cdev);
+
+ return 0;
+}
+
+static int tsensor_unbind(struct thermal_zone_device *thz,
+ struct thermal_cooling_device *cdev)
+{
+ int i;
+ struct tegra_tsensor_data *data = thz->devdata;
+
+ if (cdev == data->plat_data.passive.cdev)
+ return thermal_zone_unbind_cooling_device(thz, 0, cdev);
+
+ for (i = 0; data->plat_data.active[i].cdev; i++)
+ if (cdev == data->plat_data.active[i].cdev)
+ return thermal_zone_unbind_cooling_device(thz, i+1,
+ cdev);
+
+ return 0;
+}
+
+static int tsensor_get_trip_temp(struct thermal_zone_device *thz,
+ int trip,
+ unsigned long *temp)
+{
+ struct tegra_tsensor_data *data = thz->devdata;
+ if (trip == 0)
+ *temp = data->plat_data.passive.trip_temp;
+ else
+ *temp = data->plat_data.active[trip-1].trip_temp;
+ return 0;
+}
+
+static int tsensor_get_trip_type(struct thermal_zone_device *thz,
+ int trip,
+ enum thermal_trip_type *type)
+{
+ *type = (trip == 0) ? THERMAL_TRIP_PASSIVE : THERMAL_TRIP_ACTIVE;
+ return 0;
+}
+
+
+static struct thermal_zone_device_ops tsensor_ops = {
+ .get_temp = tsensor_get_temp,
+ .bind = tsensor_bind,
+ .unbind = tsensor_unbind,
+ .get_trip_type = tsensor_get_trip_type,
+ .get_trip_temp = tsensor_get_trip_temp,
+};
+#endif
+
static int __devinit tegra_tsensor_probe(struct platform_device *pdev)
{
struct tegra_tsensor_data *data;
@@ -1797,6 +1866,9 @@ static int __devinit tegra_tsensor_probe(struct platform_device *pdev)
unsigned int reg;
u8 i;
struct tegra_tsensor_platform_data *tsensor_data;
+#ifdef CONFIG_THERMAL
+ int num_trips = 0;
+#endif
data = kzalloc(sizeof(struct tegra_tsensor_data), GFP_KERNEL);
if (!data) {
@@ -1907,8 +1979,32 @@ static int __devinit tegra_tsensor_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "end tegra_tsensor_probe\n");
tsensor_data = pdev->dev.platform_data;
- if (tsensor_data->probe_callback)
- tsensor_data->probe_callback(data);
+
+ memcpy(&data->plat_data, tsensor_data,
+ sizeof(struct tegra_tsensor_platform_data));
+
+ tsensor_set_limits(data, tsensor_data->shutdown_temp, TSENSOR_TH3);
+
+#ifdef CONFIG_THERMAL
+ if (tsensor_data->passive.cdev)
+ num_trips++;
+
+ for (i = 0; tsensor_data->active[i].cdev; i++)
+ num_trips++;
+
+ data->thz = thermal_zone_device_register("tsensor",
+ num_trips,
+ data,
+ &tsensor_ops,
+ tsensor_data->passive.tc1,
+ tsensor_data->passive.tc2,
+ tsensor_data->passive.passive_delay,
+ 0);
+ if (IS_ERR_OR_NULL(data->thz))
+ goto err6;
+
+ tsensor_update(data);
+#endif
return 0;
err6: