aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/ds1621.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2008-07-21 00:55:14 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2008-07-21 00:55:14 -0400
commit908cf4b925e419bc74f3297b2f0e51d6f8a81da2 (patch)
tree6c2da79366d4695a9c2560ab18259eca8a2a25b4 /drivers/hwmon/ds1621.c
parent92c49890922d54cba4b1eadeb0b185773c2c9570 (diff)
parent14b395e35d1afdd8019d11b92e28041fad591b71 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6 into next
Diffstat (limited to 'drivers/hwmon/ds1621.c')
-rw-r--r--drivers/hwmon/ds1621.c99
1 files changed, 47 insertions, 52 deletions
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index 5f300ffed657..7415381601c3 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -72,7 +72,6 @@ static const u8 DS1621_REG_TEMP[3] = {
72 72
73/* Each client has this additional data */ 73/* Each client has this additional data */
74struct ds1621_data { 74struct ds1621_data {
75 struct i2c_client client;
76 struct device *hwmon_dev; 75 struct device *hwmon_dev;
77 struct mutex update_lock; 76 struct mutex update_lock;
78 char valid; /* !=0 if following fields are valid */ 77 char valid; /* !=0 if following fields are valid */
@@ -82,20 +81,32 @@ struct ds1621_data {
82 u8 conf; /* Register encoding, combined */ 81 u8 conf; /* Register encoding, combined */
83}; 82};
84 83
85static int ds1621_attach_adapter(struct i2c_adapter *adapter); 84static int ds1621_probe(struct i2c_client *client,
86static int ds1621_detect(struct i2c_adapter *adapter, int address, 85 const struct i2c_device_id *id);
87 int kind); 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); 88static void ds1621_init_client(struct i2c_client *client);
89static int ds1621_detach_client(struct i2c_client *client); 89static int ds1621_remove(struct i2c_client *client);
90static struct ds1621_data *ds1621_update_client(struct device *dev); 90static struct ds1621_data *ds1621_update_client(struct device *dev);
91 91
92static const struct i2c_device_id ds1621_id[] = {
93 { "ds1621", ds1621 },
94 { "ds1625", ds1621 },
95 { }
96};
97MODULE_DEVICE_TABLE(i2c, ds1621_id);
98
92/* This is the driver that will be inserted */ 99/* This is the driver that will be inserted */
93static struct i2c_driver ds1621_driver = { 100static struct i2c_driver ds1621_driver = {
101 .class = I2C_CLASS_HWMON,
94 .driver = { 102 .driver = {
95 .name = "ds1621", 103 .name = "ds1621",
96 }, 104 },
97 .attach_adapter = ds1621_attach_adapter, 105 .probe = ds1621_probe,
98 .detach_client = ds1621_detach_client, 106 .remove = ds1621_remove,
107 .id_table = ds1621_id,
108 .detect = ds1621_detect,
109 .address_data = &addr_data,
99}; 110};
100 111
101/* All registers are word-sized, except for the configuration register. 112/* All registers are word-sized, except for the configuration register.
@@ -199,40 +210,18 @@ static const struct attribute_group ds1621_group = {
199}; 210};
200 211
201 212
202static int ds1621_attach_adapter(struct i2c_adapter *adapter) 213/* Return 0 if detection is successful, -ENODEV otherwise */
203{ 214static int ds1621_detect(struct i2c_client *client, int kind,
204 if (!(adapter->class & I2C_CLASS_HWMON)) 215 struct i2c_board_info *info)
205 return 0;
206 return i2c_probe(adapter, &addr_data, ds1621_detect);
207}
208
209/* This function is called by i2c_probe */
210static int ds1621_detect(struct i2c_adapter *adapter, int address,
211 int kind)
212{ 216{
217 struct i2c_adapter *adapter = client->adapter;
213 int conf, temp; 218 int conf, temp;
214 struct i2c_client *client; 219 int i;
215 struct ds1621_data *data;
216 int i, err = 0;
217 220
218 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA 221 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
219 | I2C_FUNC_SMBUS_WORD_DATA 222 | I2C_FUNC_SMBUS_WORD_DATA
220 | I2C_FUNC_SMBUS_WRITE_BYTE)) 223 | I2C_FUNC_SMBUS_WRITE_BYTE))
221 goto exit; 224 return -ENODEV;
222
223 /* OK. For now, we presume we have a valid client. We now create the
224 client structure, even though we cannot fill it completely yet.
225 But it allows us to access ds1621_{read,write}_value. */
226 if (!(data = kzalloc(sizeof(struct ds1621_data), GFP_KERNEL))) {
227 err = -ENOMEM;
228 goto exit;
229 }
230
231 client = &data->client;
232 i2c_set_clientdata(client, data);
233 client->addr = address;
234 client->adapter = adapter;
235 client->driver = &ds1621_driver;
236 225
237 /* Now, we do the remaining detection. It is lousy. */ 226 /* Now, we do the remaining detection. It is lousy. */
238 if (kind < 0) { 227 if (kind < 0) {
@@ -241,29 +230,41 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address,
241 improbable in our case. */ 230 improbable in our case. */
242 conf = ds1621_read_value(client, DS1621_REG_CONF); 231 conf = ds1621_read_value(client, DS1621_REG_CONF);
243 if (conf & DS1621_REG_CONFIG_NVB) 232 if (conf & DS1621_REG_CONFIG_NVB)
244 goto exit_free; 233 return -ENODEV;
245 /* The 7 lowest bits of a temperature should always be 0. */ 234 /* The 7 lowest bits of a temperature should always be 0. */
246 for (i = 0; i < ARRAY_SIZE(data->temp); i++) { 235 for (i = 0; i < ARRAY_SIZE(DS1621_REG_TEMP); i++) {
247 temp = ds1621_read_value(client, DS1621_REG_TEMP[i]); 236 temp = ds1621_read_value(client, DS1621_REG_TEMP[i]);
248 if (temp & 0x007f) 237 if (temp & 0x007f)
249 goto exit_free; 238 return -ENODEV;
250 } 239 }
251 } 240 }
252 241
253 /* Fill in remaining client fields and put it into the global list */ 242 strlcpy(info->type, "ds1621", I2C_NAME_SIZE);
254 strlcpy(client->name, "ds1621", I2C_NAME_SIZE);
255 mutex_init(&data->update_lock);
256 243
257 /* Tell the I2C layer a new client has arrived */ 244 return 0;
258 if ((err = i2c_attach_client(client))) 245}
259 goto exit_free; 246
247static int ds1621_probe(struct i2c_client *client,
248 const struct i2c_device_id *id)
249{
250 struct ds1621_data *data;
251 int err;
252
253 data = kzalloc(sizeof(struct ds1621_data), GFP_KERNEL);
254 if (!data) {
255 err = -ENOMEM;
256 goto exit;
257 }
258
259 i2c_set_clientdata(client, data);
260 mutex_init(&data->update_lock);
260 261
261 /* Initialize the DS1621 chip */ 262 /* Initialize the DS1621 chip */
262 ds1621_init_client(client); 263 ds1621_init_client(client);
263 264
264 /* Register sysfs hooks */ 265 /* Register sysfs hooks */
265 if ((err = sysfs_create_group(&client->dev.kobj, &ds1621_group))) 266 if ((err = sysfs_create_group(&client->dev.kobj, &ds1621_group)))
266 goto exit_detach; 267 goto exit_free;
267 268
268 data->hwmon_dev = hwmon_device_register(&client->dev); 269 data->hwmon_dev = hwmon_device_register(&client->dev);
269 if (IS_ERR(data->hwmon_dev)) { 270 if (IS_ERR(data->hwmon_dev)) {
@@ -275,25 +276,19 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address,
275 276
276 exit_remove_files: 277 exit_remove_files:
277 sysfs_remove_group(&client->dev.kobj, &ds1621_group); 278 sysfs_remove_group(&client->dev.kobj, &ds1621_group);
278 exit_detach:
279 i2c_detach_client(client);
280 exit_free: 279 exit_free:
281 kfree(data); 280 kfree(data);
282 exit: 281 exit:
283 return err; 282 return err;
284} 283}
285 284
286static int ds1621_detach_client(struct i2c_client *client) 285static int ds1621_remove(struct i2c_client *client)
287{ 286{
288 struct ds1621_data *data = i2c_get_clientdata(client); 287 struct ds1621_data *data = i2c_get_clientdata(client);
289 int err;
290 288
291 hwmon_device_unregister(data->hwmon_dev); 289 hwmon_device_unregister(data->hwmon_dev);
292 sysfs_remove_group(&client->dev.kobj, &ds1621_group); 290 sysfs_remove_group(&client->dev.kobj, &ds1621_group);
293 291
294 if ((err = i2c_detach_client(client)))
295 return err;
296
297 kfree(data); 292 kfree(data);
298 293
299 return 0; 294 return 0;