aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/ds1621.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/ds1621.c')
-rw-r--r--drivers/hwmon/ds1621.c172
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
84static int ds1621_probe(struct i2c_client *client, 84/* Temperature registers are word-sized.
85 const struct i2c_device_id *id);
86static int ds1621_detect(struct i2c_client *client, int kind,
87 struct i2c_board_info *info);
88static void ds1621_init_client(struct i2c_client *client);
89static int ds1621_remove(struct i2c_client *client);
90static struct ds1621_data *ds1621_update_client(struct device *dev);
91
92static const struct i2c_device_id ds1621_id[] = {
93 { "ds1621", ds1621 },
94 { "ds1625", ds1621 },
95 { }
96};
97MODULE_DEVICE_TABLE(i2c, ds1621_id);
98
99/* This is the driver that will be inserted */
100static 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. */
115static int ds1621_read_value(struct i2c_client *client, u8 reg) 87static 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
123static int ds1621_write_value(struct i2c_client *client, u8 reg, u16 value) 97static 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
131static void ds1621_init_client(struct i2c_client *client) 102static 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
123static 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
149static ssize_t show_temp(struct device *dev, struct device_attribute *da, 162static 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
311static const struct i2c_device_id ds1621_id[] = {
312 { "ds1621", ds1621 },
313 { "ds1625", ds1621 },
314 { }
315};
316MODULE_DEVICE_TABLE(i2c, ds1621_id);
297 317
298static struct ds1621_data *ds1621_update_client(struct device *dev) 318/* This is the driver that will be inserted */
299{ 319static 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
337static int __init ds1621_init(void) 331static int __init ds1621_init(void)
338{ 332{