diff options
Diffstat (limited to 'drivers/hwmon/ds1621.c')
-rw-r--r-- | drivers/hwmon/ds1621.c | 172 |
1 files changed, 83 insertions, 89 deletions
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c index 7415381601c3..53f88f511816 100644 --- a/drivers/hwmon/ds1621.c +++ b/drivers/hwmon/ds1621.c | |||
@@ -81,71 +81,84 @@ struct ds1621_data { | |||
81 | u8 conf; /* Register encoding, combined */ | 81 | u8 conf; /* Register encoding, combined */ |
82 | }; | 82 | }; |
83 | 83 | ||
84 | static int ds1621_probe(struct i2c_client *client, | 84 | /* Temperature registers are word-sized. |
85 | const struct i2c_device_id *id); | ||
86 | static int ds1621_detect(struct i2c_client *client, int kind, | ||
87 | struct i2c_board_info *info); | ||
88 | static void ds1621_init_client(struct i2c_client *client); | ||
89 | static int ds1621_remove(struct i2c_client *client); | ||
90 | static struct ds1621_data *ds1621_update_client(struct device *dev); | ||
91 | |||
92 | static const struct i2c_device_id ds1621_id[] = { | ||
93 | { "ds1621", ds1621 }, | ||
94 | { "ds1625", ds1621 }, | ||
95 | { } | ||
96 | }; | ||
97 | MODULE_DEVICE_TABLE(i2c, ds1621_id); | ||
98 | |||
99 | /* This is the driver that will be inserted */ | ||
100 | static struct i2c_driver ds1621_driver = { | ||
101 | .class = I2C_CLASS_HWMON, | ||
102 | .driver = { | ||
103 | .name = "ds1621", | ||
104 | }, | ||
105 | .probe = ds1621_probe, | ||
106 | .remove = ds1621_remove, | ||
107 | .id_table = ds1621_id, | ||
108 | .detect = ds1621_detect, | ||
109 | .address_data = &addr_data, | ||
110 | }; | ||
111 | |||
112 | /* All registers are word-sized, except for the configuration register. | ||
113 | DS1621 uses a high-byte first convention, which is exactly opposite to | 85 | DS1621 uses a high-byte first convention, which is exactly opposite to |
114 | the SMBus standard. */ | 86 | the SMBus standard. */ |
115 | static int ds1621_read_value(struct i2c_client *client, u8 reg) | 87 | static int ds1621_read_temp(struct i2c_client *client, u8 reg) |
116 | { | 88 | { |
117 | if (reg == DS1621_REG_CONF) | 89 | int ret; |
118 | return i2c_smbus_read_byte_data(client, reg); | 90 | |
119 | else | 91 | ret = i2c_smbus_read_word_data(client, reg); |
120 | return swab16(i2c_smbus_read_word_data(client, reg)); | 92 | if (ret < 0) |
93 | return ret; | ||
94 | return swab16(ret); | ||
121 | } | 95 | } |
122 | 96 | ||
123 | static int ds1621_write_value(struct i2c_client *client, u8 reg, u16 value) | 97 | static int ds1621_write_temp(struct i2c_client *client, u8 reg, u16 value) |
124 | { | 98 | { |
125 | if (reg == DS1621_REG_CONF) | 99 | return i2c_smbus_write_word_data(client, reg, swab16(value)); |
126 | return i2c_smbus_write_byte_data(client, reg, value); | ||
127 | else | ||
128 | return i2c_smbus_write_word_data(client, reg, swab16(value)); | ||
129 | } | 100 | } |
130 | 101 | ||
131 | static void ds1621_init_client(struct i2c_client *client) | 102 | static void ds1621_init_client(struct i2c_client *client) |
132 | { | 103 | { |
133 | int reg = ds1621_read_value(client, DS1621_REG_CONF); | 104 | u8 conf, new_conf; |
105 | |||
106 | new_conf = conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); | ||
134 | /* switch to continuous conversion mode */ | 107 | /* switch to continuous conversion mode */ |
135 | reg &= ~ DS1621_REG_CONFIG_1SHOT; | 108 | new_conf &= ~DS1621_REG_CONFIG_1SHOT; |
136 | 109 | ||
137 | /* setup output polarity */ | 110 | /* setup output polarity */ |
138 | if (polarity == 0) | 111 | if (polarity == 0) |
139 | reg &= ~DS1621_REG_CONFIG_POLARITY; | 112 | new_conf &= ~DS1621_REG_CONFIG_POLARITY; |
140 | else if (polarity == 1) | 113 | else if (polarity == 1) |
141 | reg |= DS1621_REG_CONFIG_POLARITY; | 114 | new_conf |= DS1621_REG_CONFIG_POLARITY; |
142 | 115 | ||
143 | ds1621_write_value(client, DS1621_REG_CONF, reg); | 116 | if (conf != new_conf) |
117 | i2c_smbus_write_byte_data(client, DS1621_REG_CONF, new_conf); | ||
144 | 118 | ||
145 | /* start conversion */ | 119 | /* start conversion */ |
146 | i2c_smbus_write_byte(client, DS1621_COM_START); | 120 | i2c_smbus_write_byte(client, DS1621_COM_START); |
147 | } | 121 | } |
148 | 122 | ||
123 | static struct ds1621_data *ds1621_update_client(struct device *dev) | ||
124 | { | ||
125 | struct i2c_client *client = to_i2c_client(dev); | ||
126 | struct ds1621_data *data = i2c_get_clientdata(client); | ||
127 | u8 new_conf; | ||
128 | |||
129 | mutex_lock(&data->update_lock); | ||
130 | |||
131 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | ||
132 | || !data->valid) { | ||
133 | int i; | ||
134 | |||
135 | dev_dbg(&client->dev, "Starting ds1621 update\n"); | ||
136 | |||
137 | data->conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); | ||
138 | |||
139 | for (i = 0; i < ARRAY_SIZE(data->temp); i++) | ||
140 | data->temp[i] = ds1621_read_temp(client, | ||
141 | DS1621_REG_TEMP[i]); | ||
142 | |||
143 | /* reset alarms if necessary */ | ||
144 | new_conf = data->conf; | ||
145 | if (data->temp[0] > data->temp[1]) /* input > min */ | ||
146 | new_conf &= ~DS1621_ALARM_TEMP_LOW; | ||
147 | if (data->temp[0] < data->temp[2]) /* input < max */ | ||
148 | new_conf &= ~DS1621_ALARM_TEMP_HIGH; | ||
149 | if (data->conf != new_conf) | ||
150 | i2c_smbus_write_byte_data(client, DS1621_REG_CONF, | ||
151 | new_conf); | ||
152 | |||
153 | data->last_updated = jiffies; | ||
154 | data->valid = 1; | ||
155 | } | ||
156 | |||
157 | mutex_unlock(&data->update_lock); | ||
158 | |||
159 | return data; | ||
160 | } | ||
161 | |||
149 | static ssize_t show_temp(struct device *dev, struct device_attribute *da, | 162 | static ssize_t show_temp(struct device *dev, struct device_attribute *da, |
150 | char *buf) | 163 | char *buf) |
151 | { | 164 | { |
@@ -160,13 +173,13 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, | |||
160 | { | 173 | { |
161 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | 174 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
162 | struct i2c_client *client = to_i2c_client(dev); | 175 | struct i2c_client *client = to_i2c_client(dev); |
163 | struct ds1621_data *data = ds1621_update_client(dev); | 176 | struct ds1621_data *data = i2c_get_clientdata(client); |
164 | u16 val = LM75_TEMP_TO_REG(simple_strtol(buf, NULL, 10)); | 177 | u16 val = LM75_TEMP_TO_REG(simple_strtol(buf, NULL, 10)); |
165 | 178 | ||
166 | mutex_lock(&data->update_lock); | 179 | mutex_lock(&data->update_lock); |
167 | data->temp[attr->index] = val; | 180 | data->temp[attr->index] = val; |
168 | ds1621_write_value(client, DS1621_REG_TEMP[attr->index], | 181 | ds1621_write_temp(client, DS1621_REG_TEMP[attr->index], |
169 | data->temp[attr->index]); | 182 | data->temp[attr->index]); |
170 | mutex_unlock(&data->update_lock); | 183 | mutex_unlock(&data->update_lock); |
171 | return count; | 184 | return count; |
172 | } | 185 | } |
@@ -228,13 +241,14 @@ static int ds1621_detect(struct i2c_client *client, int kind, | |||
228 | /* The NVB bit should be low if no EEPROM write has been | 241 | /* The NVB bit should be low if no EEPROM write has been |
229 | requested during the latest 10ms, which is highly | 242 | requested during the latest 10ms, which is highly |
230 | improbable in our case. */ | 243 | improbable in our case. */ |
231 | conf = ds1621_read_value(client, DS1621_REG_CONF); | 244 | conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); |
232 | if (conf & DS1621_REG_CONFIG_NVB) | 245 | if (conf < 0 || conf & DS1621_REG_CONFIG_NVB) |
233 | return -ENODEV; | 246 | return -ENODEV; |
234 | /* The 7 lowest bits of a temperature should always be 0. */ | 247 | /* The 7 lowest bits of a temperature should always be 0. */ |
235 | for (i = 0; i < ARRAY_SIZE(DS1621_REG_TEMP); i++) { | 248 | for (i = 0; i < ARRAY_SIZE(DS1621_REG_TEMP); i++) { |
236 | temp = ds1621_read_value(client, DS1621_REG_TEMP[i]); | 249 | temp = i2c_smbus_read_word_data(client, |
237 | if (temp & 0x007f) | 250 | DS1621_REG_TEMP[i]); |
251 | if (temp < 0 || (temp & 0x7f00)) | ||
238 | return -ENODEV; | 252 | return -ENODEV; |
239 | } | 253 | } |
240 | } | 254 | } |
@@ -294,45 +308,25 @@ static int ds1621_remove(struct i2c_client *client) | |||
294 | return 0; | 308 | return 0; |
295 | } | 309 | } |
296 | 310 | ||
311 | static const struct i2c_device_id ds1621_id[] = { | ||
312 | { "ds1621", ds1621 }, | ||
313 | { "ds1625", ds1621 }, | ||
314 | { } | ||
315 | }; | ||
316 | MODULE_DEVICE_TABLE(i2c, ds1621_id); | ||
297 | 317 | ||
298 | static struct ds1621_data *ds1621_update_client(struct device *dev) | 318 | /* This is the driver that will be inserted */ |
299 | { | 319 | static struct i2c_driver ds1621_driver = { |
300 | struct i2c_client *client = to_i2c_client(dev); | 320 | .class = I2C_CLASS_HWMON, |
301 | struct ds1621_data *data = i2c_get_clientdata(client); | 321 | .driver = { |
302 | u8 new_conf; | 322 | .name = "ds1621", |
303 | 323 | }, | |
304 | mutex_lock(&data->update_lock); | 324 | .probe = ds1621_probe, |
305 | 325 | .remove = ds1621_remove, | |
306 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | 326 | .id_table = ds1621_id, |
307 | || !data->valid) { | 327 | .detect = ds1621_detect, |
308 | int i; | 328 | .address_data = &addr_data, |
309 | 329 | }; | |
310 | dev_dbg(&client->dev, "Starting ds1621 update\n"); | ||
311 | |||
312 | data->conf = ds1621_read_value(client, DS1621_REG_CONF); | ||
313 | |||
314 | for (i = 0; i < ARRAY_SIZE(data->temp); i++) | ||
315 | data->temp[i] = ds1621_read_value(client, | ||
316 | DS1621_REG_TEMP[i]); | ||
317 | |||
318 | /* reset alarms if necessary */ | ||
319 | new_conf = data->conf; | ||
320 | if (data->temp[0] > data->temp[1]) /* input > min */ | ||
321 | new_conf &= ~DS1621_ALARM_TEMP_LOW; | ||
322 | if (data->temp[0] < data->temp[2]) /* input < max */ | ||
323 | new_conf &= ~DS1621_ALARM_TEMP_HIGH; | ||
324 | if (data->conf != new_conf) | ||
325 | ds1621_write_value(client, DS1621_REG_CONF, | ||
326 | new_conf); | ||
327 | |||
328 | data->last_updated = jiffies; | ||
329 | data->valid = 1; | ||
330 | } | ||
331 | |||
332 | mutex_unlock(&data->update_lock); | ||
333 | |||
334 | return data; | ||
335 | } | ||
336 | 330 | ||
337 | static int __init ds1621_init(void) | 331 | static int __init ds1621_init(void) |
338 | { | 332 | { |