diff options
author | Jean Delvare <khali@linux-fr.org> | 2010-03-05 16:17:15 -0500 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2010-03-05 16:17:15 -0500 |
commit | 53de33427fa3d7dd62cc5ec75ce0d4e6c6d602dd (patch) | |
tree | 82a1fd88a2d132b534fe3df3e2ea536c1b5099ae /drivers/hwmon/lm90.c | |
parent | 95238364167edaf93ce2890e5f55326b63194851 (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>
Diffstat (limited to 'drivers/hwmon/lm90.c')
-rw-r--r-- | drivers/hwmon/lm90.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 4cbbf1563de6..7cc2708871ab 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); | |||
152 | static int lm90_probe(struct i2c_client *client, | 152 | static int lm90_probe(struct i2c_client *client, |
153 | const struct i2c_device_id *id); | 153 | const struct i2c_device_id *id); |
154 | static void lm90_init_client(struct i2c_client *client); | 154 | static void lm90_init_client(struct i2c_client *client); |
155 | static void lm90_alert(struct i2c_client *client, unsigned int flag); | ||
155 | static int lm90_remove(struct i2c_client *client); | 156 | static int lm90_remove(struct i2c_client *client); |
156 | static struct lm90_data *lm90_update_device(struct device *dev); | 157 | static 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 | ||
914 | static 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 | |||
898 | static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value) | 946 | static 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 | } |