aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/fscher.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/fscher.c')
-rw-r--r--drivers/hwmon/fscher.c93
1 files changed, 42 insertions, 51 deletions
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c
index ed26b66e0831..12c70e402cb2 100644
--- a/drivers/hwmon/fscher.c
+++ b/drivers/hwmon/fscher.c
@@ -106,9 +106,11 @@ I2C_CLIENT_INSMOD_1(fscher);
106 * Functions declaration 106 * Functions declaration
107 */ 107 */
108 108
109static int fscher_attach_adapter(struct i2c_adapter *adapter); 109static int fscher_probe(struct i2c_client *client,
110static int fscher_detect(struct i2c_adapter *adapter, int address, int kind); 110 const struct i2c_device_id *id);
111static int fscher_detach_client(struct i2c_client *client); 111static int fscher_detect(struct i2c_client *client, int kind,
112 struct i2c_board_info *info);
113static int fscher_remove(struct i2c_client *client);
112static struct fscher_data *fscher_update_device(struct device *dev); 114static struct fscher_data *fscher_update_device(struct device *dev);
113static void fscher_init_client(struct i2c_client *client); 115static void fscher_init_client(struct i2c_client *client);
114 116
@@ -119,12 +121,21 @@ static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value);
119 * Driver data (common to all clients) 121 * Driver data (common to all clients)
120 */ 122 */
121 123
124static const struct i2c_device_id fscher_id[] = {
125 { "fscher", fscher },
126 { }
127};
128
122static struct i2c_driver fscher_driver = { 129static struct i2c_driver fscher_driver = {
130 .class = I2C_CLASS_HWMON,
123 .driver = { 131 .driver = {
124 .name = "fscher", 132 .name = "fscher",
125 }, 133 },
126 .attach_adapter = fscher_attach_adapter, 134 .probe = fscher_probe,
127 .detach_client = fscher_detach_client, 135 .remove = fscher_remove,
136 .id_table = fscher_id,
137 .detect = fscher_detect,
138 .address_data = &addr_data,
128}; 139};
129 140
130/* 141/*
@@ -132,7 +143,6 @@ static struct i2c_driver fscher_driver = {
132 */ 143 */
133 144
134struct fscher_data { 145struct fscher_data {
135 struct i2c_client client;
136 struct device *hwmon_dev; 146 struct device *hwmon_dev;
137 struct mutex update_lock; 147 struct mutex update_lock;
138 char valid; /* zero until following fields are valid */ 148 char valid; /* zero until following fields are valid */
@@ -283,38 +293,14 @@ static const struct attribute_group fscher_group = {
283 * Real code 293 * Real code
284 */ 294 */
285 295
286static int fscher_attach_adapter(struct i2c_adapter *adapter) 296/* Return 0 if detection is successful, -ENODEV otherwise */
287{ 297static int fscher_detect(struct i2c_client *new_client, int kind,
288 if (!(adapter->class & I2C_CLASS_HWMON)) 298 struct i2c_board_info *info)
289 return 0;
290 return i2c_probe(adapter, &addr_data, fscher_detect);
291}
292
293static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
294{ 299{
295 struct i2c_client *new_client; 300 struct i2c_adapter *adapter = new_client->adapter;
296 struct fscher_data *data;
297 int err = 0;
298 301
299 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 302 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
300 goto exit; 303 return -ENODEV;
301
302 /* OK. For now, we presume we have a valid client. We now create the
303 * client structure, even though we cannot fill it completely yet.
304 * But it allows us to access i2c_smbus_read_byte_data. */
305 if (!(data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL))) {
306 err = -ENOMEM;
307 goto exit;
308 }
309
310 /* The common I2C client data is placed right before the
311 * Hermes-specific data. */
312 new_client = &data->client;
313 i2c_set_clientdata(new_client, data);
314 new_client->addr = address;
315 new_client->adapter = adapter;
316 new_client->driver = &fscher_driver;
317 new_client->flags = 0;
318 304
319 /* Do the remaining detection unless force or force_fscher parameter */ 305 /* Do the remaining detection unless force or force_fscher parameter */
320 if (kind < 0) { 306 if (kind < 0) {
@@ -324,24 +310,35 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
324 FSCHER_REG_IDENT_1) != 0x45) /* 'E' */ 310 FSCHER_REG_IDENT_1) != 0x45) /* 'E' */
325 || (i2c_smbus_read_byte_data(new_client, 311 || (i2c_smbus_read_byte_data(new_client,
326 FSCHER_REG_IDENT_2) != 0x52)) /* 'R' */ 312 FSCHER_REG_IDENT_2) != 0x52)) /* 'R' */
327 goto exit_free; 313 return -ENODEV;
314 }
315
316 strlcpy(info->type, "fscher", I2C_NAME_SIZE);
317
318 return 0;
319}
320
321static int fscher_probe(struct i2c_client *new_client,
322 const struct i2c_device_id *id)
323{
324 struct fscher_data *data;
325 int err;
326
327 data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL);
328 if (!data) {
329 err = -ENOMEM;
330 goto exit;
328 } 331 }
329 332
330 /* Fill in the remaining client fields and put it into the 333 i2c_set_clientdata(new_client, data);
331 * global list */
332 strlcpy(new_client->name, "fscher", I2C_NAME_SIZE);
333 data->valid = 0; 334 data->valid = 0;
334 mutex_init(&data->update_lock); 335 mutex_init(&data->update_lock);
335 336
336 /* Tell the I2C layer a new client has arrived */
337 if ((err = i2c_attach_client(new_client)))
338 goto exit_free;
339
340 fscher_init_client(new_client); 337 fscher_init_client(new_client);
341 338
342 /* Register sysfs hooks */ 339 /* Register sysfs hooks */
343 if ((err = sysfs_create_group(&new_client->dev.kobj, &fscher_group))) 340 if ((err = sysfs_create_group(&new_client->dev.kobj, &fscher_group)))
344 goto exit_detach; 341 goto exit_free;
345 342
346 data->hwmon_dev = hwmon_device_register(&new_client->dev); 343 data->hwmon_dev = hwmon_device_register(&new_client->dev);
347 if (IS_ERR(data->hwmon_dev)) { 344 if (IS_ERR(data->hwmon_dev)) {
@@ -353,25 +350,19 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
353 350
354exit_remove_files: 351exit_remove_files:
355 sysfs_remove_group(&new_client->dev.kobj, &fscher_group); 352 sysfs_remove_group(&new_client->dev.kobj, &fscher_group);
356exit_detach:
357 i2c_detach_client(new_client);
358exit_free: 353exit_free:
359 kfree(data); 354 kfree(data);
360exit: 355exit:
361 return err; 356 return err;
362} 357}
363 358
364static int fscher_detach_client(struct i2c_client *client) 359static int fscher_remove(struct i2c_client *client)
365{ 360{
366 struct fscher_data *data = i2c_get_clientdata(client); 361 struct fscher_data *data = i2c_get_clientdata(client);
367 int err;
368 362
369 hwmon_device_unregister(data->hwmon_dev); 363 hwmon_device_unregister(data->hwmon_dev);
370 sysfs_remove_group(&client->dev.kobj, &fscher_group); 364 sysfs_remove_group(&client->dev.kobj, &fscher_group);
371 365
372 if ((err = i2c_detach_client(client)))
373 return err;
374
375 kfree(data); 366 kfree(data);
376 return 0; 367 return 0;
377} 368}