diff options
author | Joshua Primero <jprimero@nvidia.com> | 2011-10-14 00:21:06 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 01:06:42 -0700 |
commit | c1ef32a9072f5e1d157dfe0e3c52d9142be8dc6a (patch) | |
tree | 9b934c6d96f48d62ed6f1523468a97cd36c8264d | |
parent | 76a628b016421dc8f586ccec01023acf63411110 (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>
Rebase-Id: R226968afc7471d8967fd7ab21cce15f1a90ee8a4
-rw-r--r-- | drivers/misc/nct1008.c | 337 | ||||
-rw-r--r-- | include/linux/nct1008.h | 4 |
2 files changed, 49 insertions, 292 deletions
diff --git a/drivers/misc/nct1008.c b/drivers/misc/nct1008.c index 3b885a32a86b..daeb5505a919 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 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 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 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 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 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 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 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 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 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 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); diff --git a/include/linux/nct1008.h b/include/linux/nct1008.h index 328dd7863053..202eeaa5ed6d 100644 --- a/include/linux/nct1008.h +++ b/include/linux/nct1008.h @@ -57,13 +57,9 @@ struct nct1008_data { u8 limits_sz; void (*alarm_fn)(bool raised); struct regulator *nct_reg; -#ifdef CONFIG_TEGRA_THERMAL_SYSFS - struct thermal_zone_device *thz; -#endif long current_lo_limit; long current_hi_limit; - long shutdown_temp; void (*alert_func)(void *); void *alert_data; }; |