summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
authorJoshua Primero <jprimero@nvidia.com>2012-01-19 16:42:10 -0800
committerSimone Willett <swillett@nvidia.com>2012-02-27 20:46:14 -0800
commit2b382eec86290b09660a9499598a4d9c55abe556 (patch)
tree3f65d2c3887285443a218ff500834d386f0bfacc /drivers/misc
parent566594ce3b1dbfc8397a62826992a0794612f51a (diff)
drivers: misc: nct: Fixed nct interrupt handler
Fixed nct bug where interrupts would go missing because thermal_alert would not correctly set the state of the thermal device. Change-Id: I09f4e7816fe606e576b257281acd498428f0d941 Signed-off-by: Joshua Primero <jprimero@nvidia.com> Reviewed-on: http://git-master/r/84674 (cherry picked from commit 5bba6f1b63225ce9ab0ab45a8513541d4435ace5) Reviewed-on: http://git-master/r/85945 Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/nct1008.c91
1 files changed, 11 insertions, 80 deletions
diff --git a/drivers/misc/nct1008.c b/drivers/misc/nct1008.c
index a9a0891f5c75..643f91d69b4d 100644
--- a/drivers/misc/nct1008.c
+++ b/drivers/misc/nct1008.c
@@ -488,99 +488,34 @@ static int nct1008_disable(struct i2c_client *client)
return err;
}
-static int nct1008_disable_alert(struct nct1008_data *data)
+static int nct1008_within_limits(struct nct1008_data *data)
{
- struct i2c_client *client = data->client;
- int ret = 0;
- int val;
-
- /*
- * Disable ALERT# output, because these chips don't implement
- * SMBus alert correctly; they should only hold the alert line
- * low briefly.
- */
- val = i2c_smbus_read_byte_data(data->client, CONFIG_RD);
- if (val < 0) {
- dev_err(&client->dev, "%s, line=%d, disable alert failed ... "
- "i2c read error=%d\n", __func__, __LINE__, val);
- return val;
- }
- data->config = 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);
-
- return ret;
-}
-
-static int nct1008_enable_alert(struct nct1008_data *data)
-{
- int val;
- int ret;
+ int intr_status;
- val = i2c_smbus_read_byte_data(data->client, CONFIG_RD);
- if (val < 0) {
- dev_err(&data->client->dev, "%s, line=%d, enable alert "
- "failed ... i2c read error=%d\n", __func__,
- __LINE__, val);
- return val;
- }
- val &= ~(ALERT_BIT | THERM2_BIT);
- ret = i2c_smbus_write_byte_data(data->client, CONFIG_WR, val);
- if (ret) {
- dev_err(&data->client->dev, "%s: fail to enable alert, i2c "
- "write error=%d\n", __func__, ret);
- return ret;
- }
+ intr_status = i2c_smbus_read_byte_data(data->client, STATUS_RD);
- return ret;
+ return !(intr_status & (BIT(3) | BIT(4)));
}
static void nct1008_work_func(struct work_struct *work)
{
struct nct1008_data *data = container_of(work, struct nct1008_data,
work);
- int err = 0;
- int intr_status = i2c_smbus_read_byte_data(data->client, STATUS_RD);
-
- if (intr_status < 0) {
- dev_err(&data->client->dev, "%s, line=%d, i2c read error=%d\n",
- __func__, __LINE__, intr_status);
- return;
- }
- intr_status &= (BIT(3) | BIT(4));
- if (!intr_status)
- return;
+ if (data->alert_func)
+ if (!nct1008_within_limits(data))
+ data->alert_func(data->alert_data);
- 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;
- }
-
- data->alert_func(data->alert_data);
-
- nct1008_enable_alert(data);
- }
-
-
- if (err)
- dev_err(&data->client->dev, "%s: fail(error=%d)\n", __func__,
- err);
- else
- pr_debug("%s: done\n", __func__);
+ enable_irq(data->client->irq);
}
static irqreturn_t nct1008_irq(int irq, void *dev_id)
{
struct nct1008_data *data = dev_id;
+ disable_irq_nosync(irq);
schedule_work(&data->work);
+
return IRQ_HANDLED;
}
@@ -737,7 +672,7 @@ static int __devinit nct1008_configure_irq(struct nct1008_data *data)
return 0;
else
return request_irq(data->client->irq, nct1008_irq,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ IRQF_TRIGGER_LOW,
DRIVER_NAME, data);
}
@@ -794,10 +729,6 @@ int nct1008_thermal_set_limits(struct nct1008_data *data,
if (lo_limit >= hi_limit)
return -EINVAL;
- if (data->current_lo_limit == lo_limit &&
- data->current_hi_limit == hi_limit)
- return 0;
-
if (data->current_lo_limit != lo_limit) {
value = temperature_to_value(extended_range, lo_limit);
pr_debug("%s: set lo_limit %ld\n", __func__, lo_limit);