Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 186399
b: refs/heads/master
c: 53de334
h: refs/heads/master
i:
  186397: c852e24
  186395: 4c98c7c
  186391: 569f43e
  186383: bd3bd31
  186367: 7a43816
v: v3
  • Loading branch information
Jean Delvare committed Mar 5, 2010
1 parent 4e83668 commit 991aa60
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 95238364167edaf93ce2890e5f55326b63194851
refs/heads/master: 53de33427fa3d7dd62cc5ec75ce0d4e6c6d602dd
12 changes: 12 additions & 0 deletions trunk/Documentation/hwmon/lm90
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,18 @@ The lm90 driver will not update its values more frequently than every
other second; reading them more often will do no harm, but will return
'old' values.

SMBus Alert Support
-------------------

This driver has basic support for SMBus alert. When an alert is received,
the status register is read and the faulty temperature channel is logged.

The Analog Devices chips (ADM1032 and ADT7461) do not implement the SMBus
alert protocol properly so additional care is needed: the ALERT output is
disabled when an alert is received, and is re-enabled only when the alarm
is gone. Otherwise the chip would block alerts from other chips in the bus
as long as the alarm is active.

PEC Support
-----------

Expand Down
63 changes: 63 additions & 0 deletions trunk/drivers/hwmon/lm90.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ static int lm90_detect(struct i2c_client *client, struct i2c_board_info *info);
static int lm90_probe(struct i2c_client *client,
const struct i2c_device_id *id);
static void lm90_init_client(struct i2c_client *client);
static void lm90_alert(struct i2c_client *client, unsigned int flag);
static int lm90_remove(struct i2c_client *client);
static struct lm90_data *lm90_update_device(struct device *dev);

Expand Down Expand Up @@ -186,6 +187,7 @@ static struct i2c_driver lm90_driver = {
},
.probe = lm90_probe,
.remove = lm90_remove,
.alert = lm90_alert,
.id_table = lm90_id,
.detect = lm90_detect,
.address_list = normal_i2c,
Expand All @@ -204,6 +206,7 @@ struct lm90_data {
int flags;

u8 config_orig; /* Original configuration register value */
u8 alert_alarms; /* Which alarm bits trigger ALERT# */

/* registers values */
s8 temp8[4]; /* 0: local low limit
Expand Down Expand Up @@ -806,6 +809,19 @@ static int lm90_probe(struct i2c_client *new_client,
new_client->flags &= ~I2C_CLIENT_PEC;
}

/* Different devices have different alarm bits triggering the
* ALERT# output */
switch (data->kind) {
case lm90:
case lm99:
case lm86:
data->alert_alarms = 0x7b;
break;
default:
data->alert_alarms = 0x7c;
break;
}

/* Initialize the LM90 chip */
lm90_init_client(new_client);

Expand Down Expand Up @@ -895,6 +911,38 @@ static int lm90_remove(struct i2c_client *client)
return 0;
}

static void lm90_alert(struct i2c_client *client, unsigned int flag)
{
struct lm90_data *data = i2c_get_clientdata(client);
u8 config, alarms;

lm90_read_reg(client, LM90_REG_R_STATUS, &alarms);
if ((alarms & 0x7f) == 0) {
dev_info(&client->dev, "Everything OK\n");
} else {
if (alarms & 0x61)
dev_warn(&client->dev,
"temp%d out of range, please check!\n", 1);
if (alarms & 0x1a)
dev_warn(&client->dev,
"temp%d out of range, please check!\n", 2);
if (alarms & 0x04)
dev_warn(&client->dev,
"temp%d diode open, please check!\n", 2);

/* Disable ALERT# output, because these chips don't implement
SMBus alert correctly; they should only hold the alert line
low briefly. */
if ((data->kind == adm1032 || data->kind == adt7461)
&& (alarms & data->alert_alarms)) {
dev_dbg(&client->dev, "Disabling ALERT#\n");
lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
config | 0x80);
}
}
}

static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value)
{
int err;
Expand Down Expand Up @@ -982,6 +1030,21 @@ static struct lm90_data *lm90_update_device(struct device *dev)
}
lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms);

/* Re-enable ALERT# output if it was originally enabled and
* relevant alarms are all clear */
if ((data->config_orig & 0x80) == 0
&& (data->alarms & data->alert_alarms) == 0) {
u8 config;

lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
if (config & 0x80) {
dev_dbg(&client->dev, "Re-enabling ALERT#\n");
i2c_smbus_write_byte_data(client,
LM90_REG_W_CONFIG1,
config & ~0x80);
}
}

data->last_updated = jiffies;
data->valid = 1;
}
Expand Down

0 comments on commit 991aa60

Please sign in to comment.