aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2010-03-05 16:17:15 -0500
committerJean Delvare <khali@linux-fr.org>2010-03-05 16:17:15 -0500
commit53de33427fa3d7dd62cc5ec75ce0d4e6c6d602dd (patch)
tree82a1fd88a2d132b534fe3df3e2ea536c1b5099ae
parent95238364167edaf93ce2890e5f55326b63194851 (diff)
hwmon: (lm90) Add SMBus alert support
Tested successfully with an ADM1032 chip on its evaluation board. It should work fine with all other chips as well. At this point this is more of a proof-of-concept, we don't do anything terribly useful on SMBus alert: we simply log the event. But this could later evolve into libsensors signaling so that user-space applications can take an appropriate action. Signed-off-by: Jean Delvare <khali@linux-fr.org> Cc: David Brownell <dbrownell@users.sourceforge.net> Cc: Trent Piepho <tpiepho@freescale.com>
-rw-r--r--Documentation/hwmon/lm9012
-rw-r--r--drivers/hwmon/lm90.c63
2 files changed, 75 insertions, 0 deletions
diff --git a/Documentation/hwmon/lm90 b/Documentation/hwmon/lm90
index 08106ad7089..6a03dd4bcc9 100644
--- a/Documentation/hwmon/lm90
+++ b/Documentation/hwmon/lm90
@@ -173,6 +173,18 @@ The lm90 driver will not update its values more frequently than every
173other second; reading them more often will do no harm, but will return 173other second; reading them more often will do no harm, but will return
174'old' values. 174'old' values.
175 175
176SMBus Alert Support
177-------------------
178
179This driver has basic support for SMBus alert. When an alert is received,
180the status register is read and the faulty temperature channel is logged.
181
182The Analog Devices chips (ADM1032 and ADT7461) do not implement the SMBus
183alert protocol properly so additional care is needed: the ALERT output is
184disabled when an alert is received, and is re-enabled only when the alarm
185is gone. Otherwise the chip would block alerts from other chips in the bus
186as long as the alarm is active.
187
176PEC Support 188PEC Support
177----------- 189-----------
178 190
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 4cbbf1563de..7cc2708871a 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -152,6 +152,7 @@ static int lm90_detect(struct i2c_client *client, struct i2c_board_info *info);
152static int lm90_probe(struct i2c_client *client, 152static int lm90_probe(struct i2c_client *client,
153 const struct i2c_device_id *id); 153 const struct i2c_device_id *id);
154static void lm90_init_client(struct i2c_client *client); 154static void lm90_init_client(struct i2c_client *client);
155static void lm90_alert(struct i2c_client *client, unsigned int flag);
155static int lm90_remove(struct i2c_client *client); 156static int lm90_remove(struct i2c_client *client);
156static struct lm90_data *lm90_update_device(struct device *dev); 157static struct lm90_data *lm90_update_device(struct device *dev);
157 158
@@ -186,6 +187,7 @@ static struct i2c_driver lm90_driver = {
186 }, 187 },
187 .probe = lm90_probe, 188 .probe = lm90_probe,
188 .remove = lm90_remove, 189 .remove = lm90_remove,
190 .alert = lm90_alert,
189 .id_table = lm90_id, 191 .id_table = lm90_id,
190 .detect = lm90_detect, 192 .detect = lm90_detect,
191 .address_list = normal_i2c, 193 .address_list = normal_i2c,
@@ -204,6 +206,7 @@ struct lm90_data {
204 int flags; 206 int flags;
205 207
206 u8 config_orig; /* Original configuration register value */ 208 u8 config_orig; /* Original configuration register value */
209 u8 alert_alarms; /* Which alarm bits trigger ALERT# */
207 210
208 /* registers values */ 211 /* registers values */
209 s8 temp8[4]; /* 0: local low limit 212 s8 temp8[4]; /* 0: local low limit
@@ -806,6 +809,19 @@ static int lm90_probe(struct i2c_client *new_client,
806 new_client->flags &= ~I2C_CLIENT_PEC; 809 new_client->flags &= ~I2C_CLIENT_PEC;
807 } 810 }
808 811
812 /* Different devices have different alarm bits triggering the
813 * ALERT# output */
814 switch (data->kind) {
815 case lm90:
816 case lm99:
817 case lm86:
818 data->alert_alarms = 0x7b;
819 break;
820 default:
821 data->alert_alarms = 0x7c;
822 break;
823 }
824
809 /* Initialize the LM90 chip */ 825 /* Initialize the LM90 chip */
810 lm90_init_client(new_client); 826 lm90_init_client(new_client);
811 827
@@ -895,6 +911,38 @@ static int lm90_remove(struct i2c_client *client)
895 return 0; 911 return 0;
896} 912}
897 913
914static void lm90_alert(struct i2c_client *client, unsigned int flag)
915{
916 struct lm90_data *data = i2c_get_clientdata(client);
917 u8 config, alarms;
918
919 lm90_read_reg(client, LM90_REG_R_STATUS, &alarms);
920 if ((alarms & 0x7f) == 0) {
921 dev_info(&client->dev, "Everything OK\n");
922 } else {
923 if (alarms & 0x61)
924 dev_warn(&client->dev,
925 "temp%d out of range, please check!\n", 1);
926 if (alarms & 0x1a)
927 dev_warn(&client->dev,
928 "temp%d out of range, please check!\n", 2);
929 if (alarms & 0x04)
930 dev_warn(&client->dev,
931 "temp%d diode open, please check!\n", 2);
932
933 /* Disable ALERT# output, because these chips don't implement
934 SMBus alert correctly; they should only hold the alert line
935 low briefly. */
936 if ((data->kind == adm1032 || data->kind == adt7461)
937 && (alarms & data->alert_alarms)) {
938 dev_dbg(&client->dev, "Disabling ALERT#\n");
939 lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
940 i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
941 config | 0x80);
942 }
943 }
944}
945
898static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value) 946static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value)
899{ 947{
900 int err; 948 int err;
@@ -982,6 +1030,21 @@ static struct lm90_data *lm90_update_device(struct device *dev)
982 } 1030 }
983 lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms); 1031 lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms);
984 1032
1033 /* Re-enable ALERT# output if it was originally enabled and
1034 * relevant alarms are all clear */
1035 if ((data->config_orig & 0x80) == 0
1036 && (data->alarms & data->alert_alarms) == 0) {
1037 u8 config;
1038
1039 lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
1040 if (config & 0x80) {
1041 dev_dbg(&client->dev, "Re-enabling ALERT#\n");
1042 i2c_smbus_write_byte_data(client,
1043 LM90_REG_W_CONFIG1,
1044 config & ~0x80);
1045 }
1046 }
1047
985 data->last_updated = jiffies; 1048 data->last_updated = jiffies;
986 data->valid = 1; 1049 data->valid = 1;
987 } 1050 }