summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
authorJoshua Primero <jprimero@nvidia.com>2012-02-22 13:32:36 -0800
committerSimone Willett <swillett@nvidia.com>2012-03-08 15:11:06 -0800
commit30bc36f606443f5f4b6873e769f401a4ac87c33a (patch)
treefb75bfa292e097900b41f5a2efce5fb9121e3182 /drivers/misc
parent0ea0d72ae4607c61440f4333bd62718a9cea2f03 (diff)
drivers: misc: nct: Fixed spurious nct interrupts
Enabled one-shot mode in the bottom half handler of nct interrupts to force a conversion/comparison. This effectively stops repeated nct interrupts. Signed-off-by: Joshua Primero <jprimero@nvidia.com> Reviewed-on: http://git-master/r/85277 (cherry picked from commit bc90335e0201cba073333c679b2fddff7bb293f1) Change-Id: Id0bd19f8f464ffbd9079fc2910a1bbcd0e621843 Reviewed-on: http://git-master/r/88373 Reviewed-by: Joshua Primero <jprimero@nvidia.com> Tested-by: Joshua Primero <jprimero@nvidia.com> Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/nct1008.c66
1 files changed, 26 insertions, 40 deletions
diff --git a/drivers/misc/nct1008.c b/drivers/misc/nct1008.c
index 643f91d69b4d..3a8aa6b9dbd2 100644
--- a/drivers/misc/nct1008.c
+++ b/drivers/misc/nct1008.c
@@ -53,6 +53,7 @@
#define LOCAL_TEMP_LO_LIMIT_WR 0x0C
#define EXT_TEMP_HI_LIMIT_HI_BYTE_WR 0x0D
#define EXT_TEMP_LO_LIMIT_HI_BYTE_WR 0x0E
+#define ONE_SHOT 0x0F
#define OFFSET_WR 0x11
#define OFFSET_QUARTER_WR 0x12
#define EXT_THERM_LIMIT_WR 0x19
@@ -75,10 +76,14 @@
#define MAX_STR_PRINT 50
-#define MIN_SLEEP_MSEC 20
+#define MAX_CONV_TIME_ONESHOT_MS (52)
#define CELSIUS_TO_MILLICELSIUS(x) ((x)*1000)
#define MILLICELSIUS_TO_CELSIUS(x) ((x)/1000)
+
+static int conv_period_ms_table[] =
+ {16000, 8000, 4000, 2000, 1000, 500, 250, 125, 63, 32, 16};
+
static inline s8 value_to_temperature(bool extended, u8 value)
{
return extended ? (s8)(value - EXTENDED_RANGE_OFFSET) : (s8)value;
@@ -501,11 +506,26 @@ static void nct1008_work_func(struct work_struct *work)
{
struct nct1008_data *data = container_of(work, struct nct1008_data,
work);
+ int intr_status;
+ struct timespec ts;
+
+ nct1008_disable(data->client);
if (data->alert_func)
if (!nct1008_within_limits(data))
data->alert_func(data->alert_data);
+ /* Initiate one-shot conversion */
+ i2c_smbus_write_byte_data(data->client, ONE_SHOT, 0x1);
+
+ /* Give hardware necessary time to finish conversion */
+ ts = ns_to_timespec(MAX_CONV_TIME_ONESHOT_MS * 1000 * 1000);
+ hrtimer_nanosleep(&ts, NULL, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
+
+ intr_status = i2c_smbus_read_byte_data(data->client, STATUS_RD);
+
+ nct1008_enable(data->client);
+
enable_irq(data->client->irq);
}
@@ -514,7 +534,7 @@ static irqreturn_t nct1008_irq(int irq, void *dev_id)
struct nct1008_data *data = dev_id;
disable_irq_nosync(irq);
- schedule_work(&data->work);
+ queue_work(data->workqueue, &data->work);
return IRQ_HANDLED;
}
@@ -591,6 +611,8 @@ static int __devinit nct1008_configure_sensor(struct nct1008_data* data)
if (err)
goto error;
+ data->conv_period_ms = conv_period_ms_table[pdata->conv_rate];
+
/* Setup local hi and lo limits */
err = i2c_smbus_write_byte_data(client,
LOCAL_TEMP_HI_LIMIT_WR, NCT1008_MAX_TEMP);
@@ -666,6 +688,8 @@ error:
static int __devinit nct1008_configure_irq(struct nct1008_data *data)
{
+ data->workqueue = create_singlethread_workqueue("nct1008");
+
INIT_WORK(&data->work, nct1008_work_func);
if (data->client->irq < 0)
@@ -676,35 +700,6 @@ static int __devinit nct1008_configure_irq(struct nct1008_data *data)
DRIVER_NAME, data);
}
-static unsigned int get_ext_mode_delay_ms(unsigned int conv_rate)
-{
- switch (conv_rate) {
- case 0:
- return 16000;
- case 1:
- return 8000;
- case 2:
- return 4000;
- case 3:
- return 2000;
- case 4:
- return 1000;
- case 5:
- return 500;
- case 6:
- return 250;
- case 7:
- return 125;
- case 9:
- return 32;
- case 10:
- return 16;
- case 8:
- default:
- return 63;
- }
-}
-
int nct1008_thermal_get_temp(struct nct1008_data *data, long *temp)
{
return nct1008_get_temp(&data->client->dev, temp);
@@ -852,14 +847,6 @@ static int __devinit nct1008_probe(struct i2c_client *client,
if (err < 0)
err = 0; /* without debugfs we may continue */
- /* switch to extended mode reports correct temperature
- * from next measurement cycle */
- if (data->plat_data.ext_range) {
- delay = get_ext_mode_delay_ms(
- data->plat_data.conv_rate);
- msleep(delay); /* 63msec for default conv rate 0x8 */
- }
-
/* notify callback that probe is done */
if (data->plat_data.probe_callback)
data->plat_data.probe_callback(data);
@@ -916,7 +903,6 @@ static int nct1008_resume(struct i2c_client *client)
return err;
}
enable_irq(client->irq);
- schedule_work(&data->work);
return 0;
}