summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJoshua Primero <jprimero@nvidia.com>2011-10-14 00:21:06 -0700
committerVarun Wadekar <vwadekar@nvidia.com>2011-12-08 17:03:45 +0530
commitdd3e4962a22fbfa1e0b8c8d50772f0d613ad29b3 (patch)
tree9dfe15d1c7e6508fde115c82052ce11ac19c4b7a /drivers
parent0a892e234ce77f94973afbf2d00ea4239ee6b677 (diff)
misc: nct1008: Refactored nct1008 driver
Refactored nct1008 driver so that it can be controlled by the Tegra Thermal framework. Reviewed-on: http://git-master/r/58044 Reviewed-on: http://git-master/r/63339 Cherry-picked as e420f67c427173403a9669a67cfe98ad3c8482e1. Change-Id: Id47205bb2d8f148dc919de7f1a53f1c562899d5e Signed-off-by: Joshua Primero <jprimero@nvidia.com> Reviewed-on: http://git-master/r/66552 Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/misc/nct1008.c337
1 files changed, 49 insertions, 288 deletions
diff --git a/drivers/misc/nct1008.c b/drivers/misc/nct1008.c
index ad301a0b1eef..86f4030b6317 100644
--- a/drivers/misc/nct1008.c
+++ b/drivers/misc/nct1008.c
@@ -22,7 +22,6 @@
#include <linux/interrupt.h>
-#include <linux/mutex.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/slab.h>
@@ -32,7 +31,6 @@
#include <linux/nct1008.h>
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
-#include <linux/thermal.h>
#define DRIVER_NAME "nct1008"
@@ -561,7 +559,7 @@ static int nct1008_disable_alert(struct nct1008_data *data)
return val;
}
data->config = val | ALERT_BIT;
- ret = i2c_smbus_write_byte_data(client, CONFIG_WR, val | ALERT_BIT);
+ ret = i2c_smbus_write_byte_data(client, CONFIG_WR, data->config);
if (ret)
dev_err(&client->dev, "%s: fail to disable alert, i2c "
"write error=%d#\n", __func__, ret);
@@ -592,50 +590,11 @@ static int nct1008_enable_alert(struct nct1008_data *data)
return ret;
}
-/* The thermal sysfs handles notifying the throttling
- * cooling device */
-#ifndef CONFIG_TEGRA_THERMAL_SYSFS
-static bool throttle_enb;
-static void therm_throttle(struct nct1008_data *data, bool enable)
-{
- if (!data->alarm_fn) {
- dev_err(&data->client->dev, "system too hot. no way to "
- "cool down!\n");
- return;
- }
-
- if (throttle_enb != enable) {
- mutex_lock(&data->mutex);
- data->alarm_fn(enable);
- throttle_enb = enable;
- mutex_unlock(&data->mutex);
- }
-}
-#endif
-
-/* Thermal sysfs handles hysteresis */
-#ifndef CONFIG_TEGRA_THERMAL_SYSFS
- #define ALERT_HYSTERESIS_THROTTLE 1
-#endif
-
-#define ALERT_HYSTERESIS_THROTTLE 1
-#define ALERT_HYSTERESIS_EDP 3
-static int edp_thermal_zone_val = -1;
-static int current_hi_limit = -1;
-static int current_lo_limit = -1;
-
static void nct1008_work_func(struct work_struct *work)
{
struct nct1008_data *data = container_of(work, struct nct1008_data,
work);
- bool extended_range = data->plat_data.ext_range;
- long temp_milli;
- u8 value;
- int err = 0, i;
- int hysteresis;
- int nentries = data->limits_sz;
- int lo_limit = 0, hi_limit = 0;
- long throttling_ext_limit_milli;
+ int err = 0;
int intr_status = i2c_smbus_read_byte_data(data->client, STATUS_RD);
if (intr_status < 0) {
@@ -648,109 +607,20 @@ static void nct1008_work_func(struct work_struct *work)
if (!intr_status)
return;
- err = nct1008_get_temp(&data->client->dev, &temp_milli);
- if (err) {
- dev_err(&data->client->dev, "%s: get temp fail(%d)", __func__,
- err);
- return;
- }
-
- err = nct1008_disable_alert(data);
- if (err) {
- dev_err(&data->client->dev, "%s: disable alert fail(error=%d)\n"
- , __func__, err);
- return;
- }
-
- hysteresis = ALERT_HYSTERESIS_EDP;
-
-/* Thermal sysfs handles hysteresis */
-#ifndef CONFIG_TEGRA_THERMAL_SYSFS
- throttling_ext_limit_milli =
- CELSIUS_TO_MILLICELSIUS(data->plat_data.throttling_ext_limit);
-
- if (temp_milli >= throttling_ext_limit_milli) {
- /* start throttling */
- therm_throttle(data, true);
- hysteresis = ALERT_HYSTERESIS_THROTTLE;
- } else if (temp_milli <=
- (throttling_ext_limit_milli -
- ALERT_HYSTERESIS_THROTTLE)) {
- /* switch off throttling */
- therm_throttle(data, false);
- }
-#endif
-
- if (temp_milli < CELSIUS_TO_MILLICELSIUS(data->limits[0])) {
- lo_limit = 0;
- hi_limit = data->limits[0];
- } else if (temp_milli >=
- CELSIUS_TO_MILLICELSIUS(data->limits[nentries-1])) {
- lo_limit = data->limits[nentries-1] - hysteresis;
- hi_limit = data->plat_data.shutdown_ext_limit;
- } else {
- for (i = 0; (i + 1) < nentries; i++) {
- if (temp_milli >=
- CELSIUS_TO_MILLICELSIUS(data->limits[i]) &&
- temp_milli <
- CELSIUS_TO_MILLICELSIUS(data->limits[i + 1])) {
- lo_limit = data->limits[i] - hysteresis;
- hi_limit = data->limits[i + 1];
- break;
- }
+ if (data->alert_func) {
+ err = nct1008_disable_alert(data);
+ if (err) {
+ dev_err(&data->client->dev,
+ "%s: disable alert fail(error=%d)\n",
+ __func__, err);
+ return;
}
- }
-
- if (lo_limit == hi_limit) {
- err = -ENODATA;
- goto out;
- }
- if (current_lo_limit == lo_limit && current_hi_limit == hi_limit)
- goto out;
+ data->alert_func(data->alert_data);
- if (current_lo_limit != lo_limit) {
- value = temperature_to_value(extended_range, lo_limit);
- pr_debug("%s: %d\n", __func__, value);
- err = i2c_smbus_write_byte_data(data->client,
- EXT_TEMP_LO_LIMIT_HI_BYTE_WR, value);
- if (err)
- goto out;
-
- current_lo_limit = lo_limit;
+ nct1008_enable_alert(data);
}
- if (current_hi_limit != hi_limit) {
- value = temperature_to_value(extended_range, hi_limit);
- pr_debug("%s: %d\n", __func__, value);
- err = i2c_smbus_write_byte_data(data->client,
- EXT_TEMP_HI_LIMIT_HI_BYTE_WR, value);
- if (err)
- goto out;
-
- current_hi_limit = hi_limit;
- }
-
- /* inform edp governor */
- if (edp_thermal_zone_val != temp_milli)
- /*
- * FIXME: Move this direct tegra_ function call to be called
- * via a pointer in 'struct nct1008_data' (like 'alarm_fn')
- */
- tegra_edp_update_thermal_zone(
- MILLICELSIUS_TO_CELSIUS(temp_milli));
-
- edp_thermal_zone_val = temp_milli;
-
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- if (data->thz) {
- if (!data->thz->passive)
- thermal_zone_device_update(data->thz);
- }
-#endif
-
-out:
- nct1008_enable_alert(data);
if (err)
dev_err(&data->client->dev, "%s: fail(error=%d)\n", __func__,
@@ -803,7 +673,6 @@ static int __devinit nct1008_configure_sensor(struct nct1008_data* data)
s8 temp;
u8 temp2;
int err;
- int hi_limit;
if (!pdata || !pdata->supported_hwrev)
return -ENODEV;
@@ -815,15 +684,13 @@ static int __devinit nct1008_configure_sensor(struct nct1008_data* data)
goto error;
/* External temperature h/w shutdown limit */
- value = temperature_to_value(pdata->ext_range,
- pdata->shutdown_ext_limit);
+ value = temperature_to_value(pdata->ext_range, NCT1008_MAX_TEMP);
err = i2c_smbus_write_byte_data(client, EXT_THERM_LIMIT_WR, value);
if (err)
goto error;
/* Local temperature h/w shutdown limit */
- value = temperature_to_value(pdata->ext_range,
- pdata->shutdown_local_limit);
+ value = temperature_to_value(pdata->ext_range, NCT1008_MAX_TEMP);
err = i2c_smbus_write_byte_data(client, LOCAL_THERM_LIMIT_WR, value);
if (err)
goto error;
@@ -831,10 +698,7 @@ static int __devinit nct1008_configure_sensor(struct nct1008_data* data)
/* set extended range mode if needed */
if (pdata->ext_range)
data->config |= EXTENDED_RANGE_BIT;
- if (pdata->thermal_zones_sz)
- data->config &= ~(THERM2_BIT | ALERT_BIT);
- else
- data->config |= (ALERT_BIT | THERM2_BIT);
+ data->config &= ~(THERM2_BIT | ALERT_BIT);
err = i2c_smbus_write_byte_data(client, CONFIG_WR, data->config);
if (err)
@@ -845,38 +709,24 @@ static int __devinit nct1008_configure_sensor(struct nct1008_data* data)
if (err)
goto error;
- if (pdata->thermal_zones_sz) {
- data->limits = pdata->thermal_zones;
- data->limits_sz = pdata->thermal_zones_sz;
-
- /* setup alarm */
- hi_limit = pdata->thermal_zones[0];
-
- err = i2c_smbus_write_byte_data(client,
- EXT_TEMP_LO_LIMIT_HI_BYTE_WR, 0);
- if (err)
- goto error;
-
- err = i2c_smbus_write_byte_data(client,
- LOCAL_TEMP_HI_LIMIT_WR, NCT1008_MAX_TEMP);
- if (err)
- goto error;
+ /* Setup local hi and lo limits */
+ err = i2c_smbus_write_byte_data(client,
+ LOCAL_TEMP_HI_LIMIT_WR, NCT1008_MAX_TEMP);
+ if (err)
+ goto error;
- err = i2c_smbus_write_byte_data(client,
- LOCAL_TEMP_LO_LIMIT_WR, 0);
- if (err)
- goto error;
- } else {
- /*
- * External Temperature Throttling limit:
- * Applies when 'Thermal Zones' are not specified.
- */
- hi_limit = pdata->throttling_ext_limit;
- }
+ err = i2c_smbus_write_byte_data(client,
+ LOCAL_TEMP_LO_LIMIT_WR, 0);
+ if (err)
+ goto error;
- value = temperature_to_value(pdata->ext_range, hi_limit);
+ /* Setup external hi and lo limits */
+ err = i2c_smbus_write_byte_data(client,
+ EXT_TEMP_LO_LIMIT_HI_BYTE_WR, 0);
+ if (err)
+ goto error;
err = i2c_smbus_write_byte_data(client, EXT_TEMP_HI_LIMIT_HI_BYTE_WR,
- value);
+ NCT1008_MAX_TEMP);
if (err)
goto error;
@@ -919,12 +769,6 @@ static int __devinit nct1008_configure_sensor(struct nct1008_data* data)
if (err < 0)
goto error;
- /* THERM hysteresis */
- err = i2c_smbus_write_byte_data(client, THERM_HYSTERESIS_WR,
- pdata->hysteresis);
- if (err < 0)
- goto error;
-
/* register sysfs hooks */
err = sysfs_create_group(&client->dev.kobj, &nct1008_attr_group);
if (err < 0) {
@@ -932,10 +776,6 @@ static int __devinit nct1008_configure_sensor(struct nct1008_data* data)
goto error;
}
- data->alarm_fn = pdata->alarm_fn;
-
- data->current_lo_limit = -1;
- data->current_hi_limit = -1;
return 0;
error:
dev_err(&client->dev, "\n exit %s, err=%d ", __func__, err);
@@ -1027,86 +867,45 @@ int nct1008_thermal_set_limits(struct nct1008_data *data,
data->current_hi_limit = hi_limit;
}
+ return 0;
}
int nct1008_thermal_set_alert(struct nct1008_data *data,
void (*alert_func)(void *),
void *alert_data)
{
- data->alert_func = alert_func;
data->alert_data = alert_data;
+ data->alert_func = alert_func;
return 0;
}
int nct1008_thermal_set_shutdown_temp(struct nct1008_data *data,
- long shutdown_temp)
+ long shutdown_temp_milli)
{
- data->shutdown_temp = shutdown_temp;
-
- return 0;
-}
-
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
-
-static int nct1008_thermal_zone_bind(struct thermal_zone_device *thermal,
- struct thermal_cooling_device *cdevice) {
- /* Support only Thermal Throttling (1 trip) for now */
- return thermal_zone_bind_cooling_device(thermal, 0, cdevice);
-}
-
-static int nct1008_thermal_zone_unbind(struct thermal_zone_device *thermal,
- struct thermal_cooling_device *cdevice) {
- /* Support only Thermal Throttling (1 trip) for now */
- return thermal_zone_unbind_cooling_device(thermal, 0, cdevice);
-}
-
-static int nct1008_thermal_zone_get_temp(struct thermal_zone_device *thermal,
- long *temp)
-{
- struct nct1008_data *data = thermal->devdata;
-
- return nct1008_get_temp(&data->client->dev, temp);
-}
-
-static int nct1008_thermal_zone_get_trip_type(
- struct thermal_zone_device *thermal,
- int trip,
- enum thermal_trip_type *type) {
-
- /* Support only Thermal Throttling (1 trip) for now */
- if (trip != 0)
- return -EINVAL;
-
- *type = THERMAL_TRIP_PASSIVE;
-
- return 0;
-}
+ struct i2c_client *client = data->client;
+ struct nct1008_platform_data *pdata = client->dev.platform_data;
+ int err;
+ u8 value;
+ long shutdown_temp;
-static int nct1008_thermal_zone_get_trip_temp(
- struct thermal_zone_device *thermal,
- int trip,
- long *temp) {
- struct nct1008_data *data = thermal->devdata;
+ shutdown_temp = MILLICELSIUS_TO_CELSIUS(shutdown_temp_milli);
- /* Support only Thermal Throttling (1 trip) for now */
- if (trip != 0)
- return -EINVAL;
+ /* External temperature h/w shutdown limit */
+ value = temperature_to_value(pdata->ext_range, shutdown_temp);
+ err = i2c_smbus_write_byte_data(client, EXT_THERM_LIMIT_WR, value);
+ if (err)
+ return err;
- *temp = CELSIUS_TO_MILLICELSIUS(data->plat_data.throttling_ext_limit);
+ /* Local temperature h/w shutdown limit */
+ value = temperature_to_value(pdata->ext_range, shutdown_temp);
+ err = i2c_smbus_write_byte_data(client, LOCAL_THERM_LIMIT_WR, value);
+ if (err)
+ return err;
return 0;
}
-static struct thermal_zone_device_ops nct1008_thermal_zone_ops = {
- .bind = nct1008_thermal_zone_bind,
- .unbind = nct1008_thermal_zone_unbind,
- .get_temp = nct1008_thermal_zone_get_temp,
- .get_trip_type = nct1008_thermal_zone_get_trip_type,
- .get_trip_temp = nct1008_thermal_zone_get_trip_temp,
-};
-#endif
-
/*
* Manufacturer(OnSemi) recommended sequence for
* Extended Range mode is as follows
@@ -1128,11 +927,7 @@ static int __devinit nct1008_probe(struct i2c_client *client,
{
struct nct1008_data *data;
int err;
- long temp_milli;
unsigned int delay;
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- struct thermal_zone_device *thz;
-#endif
data = kzalloc(sizeof(struct nct1008_data), GFP_KERNEL);
if (!data)
@@ -1142,7 +937,6 @@ static int __devinit nct1008_probe(struct i2c_client *client,
memcpy(&data->plat_data, client->dev.platform_data,
sizeof(struct nct1008_platform_data));
i2c_set_clientdata(client, data);
- mutex_init(&data->mutex);
nct1008_power_control(data, true);
/* extended range recommended steps 1 through 4 taken care
@@ -1181,34 +975,8 @@ static int __devinit nct1008_probe(struct i2c_client *client,
data->plat_data.conv_rate);
msleep(delay); /* 63msec for default conv rate 0x8 */
}
- err = nct1008_get_temp(&data->client->dev, &temp_milli);
- if (err) {
- dev_err(&data->client->dev, "%s: get temp fail(%d)",
- __func__, err);
- return 0; /*do not fail init on the 1st read */
- }
-
- tegra_edp_update_thermal_zone(MILLICELSIUS_TO_CELSIUS(temp_milli));
-
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- thz = thermal_zone_device_register("nct1008",
- 1, /* trips */
- data,
- &nct1008_thermal_zone_ops,
- 1, /* tc1 */
- 5, /* tc2 */
- 2000, /* passive delay */
- 0); /* polling delay */
-
- if (IS_ERR(thz)) {
- data->thz = NULL;
- err = -ENODEV;
- goto error;
- }
-
- data->thz = thz;
-#endif
+ /* notify callback that probe is done */
if (data->plat_data.probe_callback)
data->plat_data.probe_callback(data);
@@ -1230,13 +998,6 @@ static int __devexit nct1008_remove(struct i2c_client *client)
if (data->dent)
debugfs_remove(data->dent);
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- if (data->thz) {
- thermal_zone_device_unregister(data->thz);
- data->thz = NULL;
- }
-#endif
-
free_irq(data->client->irq, data);
cancel_work_sync(&data->work);
sysfs_remove_group(&client->dev.kobj, &nct1008_attr_group);