Commit a3cf8593 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6

* 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6: (44 commits)
  hwmon: (w83l786ng) Convert to a new-style i2c driver
  hwmon: (w83l785ts) Convert to a new-style i2c driver
  hwmon: (w83793) Convert to a new-style i2c driver
  hwmon: (w83792d) Convert to a new-style i2c driver
  hwmon: (w83791d) Convert to a new-style i2c driver
  hwmon: (thmc50) Convert to a new-style i2c driver
  hwmon: (smsc47m192) Convert to a new-style i2c driver
  hwmon: (max6650) Convert to a new-style i2c driver
  hwmon: (max1619) Convert to a new-style i2c driver
  hwmon: (lm93) Convert to a new-style i2c driver
  hwmon: (lm92) Convert to a new-style i2c driver
  hwmon: (lm90) Convert to a new-style i2c driver
  hwmon: (lm87) Convert to a new-style i2c driver
  hwmon: (lm83) Convert to a new-style i2c driver
  hwmon: (lm80) Convert to a new-style i2c driver
  hwmon: (lm77) Convert to a new-style i2c driver
  hwmon: (lm63) Convert to a new-style i2c driver
  hwmon: (gl520sm) Convert to a new-style i2c driver
  hwmon: (gl518sm) Convert to a new-style i2c driver
  hwmon: (fscpos) Convert to a new-style i2c driver
  ...
parents 3c3622dc 33468e76
...@@ -49,7 +49,7 @@ $ modprobe max6875 force=0,0x50 ...@@ -49,7 +49,7 @@ $ modprobe max6875 force=0,0x50
The MAX6874/MAX6875 ignores address bit 0, so this driver attaches to multiple The MAX6874/MAX6875 ignores address bit 0, so this driver attaches to multiple
addresses. For example, for address 0x50, it also reserves 0x51. addresses. For example, for address 0x50, it also reserves 0x51.
The even-address instance is called 'max6875', the odd one is 'max6875 subclient'. The even-address instance is called 'max6875', the odd one is 'dummy'.
Programming the chip using i2c-dev Programming the chip using i2c-dev
......
...@@ -7,7 +7,7 @@ drivers/gpio/pca9539.c instead. ...@@ -7,7 +7,7 @@ drivers/gpio/pca9539.c instead.
Supported chips: Supported chips:
* Philips PCA9539 * Philips PCA9539
Prefix: 'pca9539' Prefix: 'pca9539'
Addresses scanned: 0x74 - 0x77 Addresses scanned: none
Datasheet: Datasheet:
http://www.semiconductors.philips.com/acrobat/datasheets/PCA9539_2.pdf http://www.semiconductors.philips.com/acrobat/datasheets/PCA9539_2.pdf
...@@ -23,6 +23,14 @@ The input sense can also be inverted. ...@@ -23,6 +23,14 @@ The input sense can also be inverted.
The 16 lines are split between two bytes. The 16 lines are split between two bytes.
Detection
---------
The PCA9539 is difficult to detect and not commonly found in PC machines,
so you have to pass the I2C bus and address of the installed PCA9539
devices explicitly to the driver at load time via the force=... parameter.
Sysfs entries Sysfs entries
------------- -------------
......
...@@ -4,13 +4,13 @@ Kernel driver pcf8574 ...@@ -4,13 +4,13 @@ Kernel driver pcf8574
Supported chips: Supported chips:
* Philips PCF8574 * Philips PCF8574
Prefix: 'pcf8574' Prefix: 'pcf8574'
Addresses scanned: I2C 0x20 - 0x27 Addresses scanned: none
Datasheet: Publicly available at the Philips Semiconductors website Datasheet: Publicly available at the Philips Semiconductors website
http://www.semiconductors.philips.com/pip/PCF8574P.html http://www.semiconductors.philips.com/pip/PCF8574P.html
* Philips PCF8574A * Philips PCF8574A
Prefix: 'pcf8574a' Prefix: 'pcf8574a'
Addresses scanned: I2C 0x38 - 0x3f Addresses scanned: none
Datasheet: Publicly available at the Philips Semiconductors website Datasheet: Publicly available at the Philips Semiconductors website
http://www.semiconductors.philips.com/pip/PCF8574P.html http://www.semiconductors.philips.com/pip/PCF8574P.html
...@@ -38,12 +38,10 @@ For more informations see the datasheet. ...@@ -38,12 +38,10 @@ For more informations see the datasheet.
Accessing PCF8574(A) via /sys interface Accessing PCF8574(A) via /sys interface
------------------------------------- -------------------------------------
! Be careful !
The PCF8574(A) is plainly impossible to detect ! Stupid chip. The PCF8574(A) is plainly impossible to detect ! Stupid chip.
So every chip with address in the interval [20..27] and [38..3f] are So, you have to pass the I2C bus and address of the installed PCF857A
detected as PCF8574(A). If you have other chips in this address and PCF8574A devices explicitly to the driver at load time via the
range, the workaround is to load this module after the one force=... parameter.
for your others chips.
On detection (i.e. insmod, modprobe et al.), directories are being On detection (i.e. insmod, modprobe et al.), directories are being
created for each detected PCF8574(A): created for each detected PCF8574(A):
......
...@@ -40,12 +40,9 @@ Detection ...@@ -40,12 +40,9 @@ Detection
--------- ---------
There is no method known to detect whether a chip on a given I2C address is There is no method known to detect whether a chip on a given I2C address is
a PCF8575 or whether it is any other I2C device. So there are two alternatives a PCF8575 or whether it is any other I2C device, so you have to pass the I2C
to let the driver find the installed PCF8575 devices: bus and address of the installed PCF8575 devices explicitly to the driver at
- Load this driver after any other I2C driver for I2C devices with addresses load time via the force=... parameter.
in the range 0x20 .. 0x27.
- Pass the I2C bus and address of the installed PCF8575 devices explicitly to
the driver at load time via the probe=... or force=... parameters.
/sys interface /sys interface
-------------- --------------
......
...@@ -23,12 +23,9 @@ ...@@ -23,12 +23,9 @@
#include "lm75.h" #include "lm75.h"
#define DRV_VERSION "0.3" #define DRV_VERSION "0.4"
/* Addresses to scan */ enum chips { ad7416, ad7417, ad7418 };
static const unsigned short normal_i2c[] = { 0x28, I2C_CLIENT_END };
/* Insmod parameters */
I2C_CLIENT_INSMOD_3(ad7416, ad7417, ad7418);
/* AD7418 registers */ /* AD7418 registers */
#define AD7418_REG_TEMP_IN 0x00 #define AD7418_REG_TEMP_IN 0x00
...@@ -46,7 +43,6 @@ static const u8 AD7418_REG_TEMP[] = { AD7418_REG_TEMP_IN, ...@@ -46,7 +43,6 @@ static const u8 AD7418_REG_TEMP[] = { AD7418_REG_TEMP_IN,
AD7418_REG_TEMP_OS }; AD7418_REG_TEMP_OS };
struct ad7418_data { struct ad7418_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct attribute_group attrs; struct attribute_group attrs;
enum chips type; enum chips type;
...@@ -58,16 +54,25 @@ struct ad7418_data { ...@@ -58,16 +54,25 @@ struct ad7418_data {
u16 in[4]; u16 in[4];
}; };
static int ad7418_attach_adapter(struct i2c_adapter *adapter); static int ad7418_probe(struct i2c_client *client,
static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int ad7418_detach_client(struct i2c_client *client); static int ad7418_remove(struct i2c_client *client);
static const struct i2c_device_id ad7418_id[] = {
{ "ad7416", ad7416 },
{ "ad7417", ad7417 },
{ "ad7418", ad7418 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ad7418_id);
static struct i2c_driver ad7418_driver = { static struct i2c_driver ad7418_driver = {
.driver = { .driver = {
.name = "ad7418", .name = "ad7418",
}, },
.attach_adapter = ad7418_attach_adapter, .probe = ad7418_probe,
.detach_client = ad7418_detach_client, .remove = ad7418_remove,
.id_table = ad7418_id,
}; };
/* All registers are word-sized, except for the configuration registers. /* All registers are word-sized, except for the configuration registers.
...@@ -192,13 +197,6 @@ static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_adc, NULL, 1); ...@@ -192,13 +197,6 @@ static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_adc, NULL, 1);
static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_adc, NULL, 2); static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_adc, NULL, 2);
static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_adc, NULL, 3); static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_adc, NULL, 3);
static int ad7418_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, ad7418_detect);
}
static struct attribute *ad7416_attributes[] = { static struct attribute *ad7416_attributes[] = {
&sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr, &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
...@@ -225,98 +223,46 @@ static struct attribute *ad7418_attributes[] = { ...@@ -225,98 +223,46 @@ static struct attribute *ad7418_attributes[] = {
NULL NULL
}; };
static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind) static int ad7418_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{ {
struct i2c_client *client; struct i2c_adapter *adapter = client->adapter;
struct ad7418_data *data; struct ad7418_data *data;
int err = 0; int err;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA)) I2C_FUNC_SMBUS_WORD_DATA)) {
err = -EOPNOTSUPP;
goto exit; goto exit;
}
if (!(data = kzalloc(sizeof(struct ad7418_data), GFP_KERNEL))) { if (!(data = kzalloc(sizeof(struct ad7418_data), GFP_KERNEL))) {
err = -ENOMEM; err = -ENOMEM;
goto exit; goto exit;
} }
client = &data->client;
client->addr = address;
client->adapter = adapter;
client->driver = &ad7418_driver;
i2c_set_clientdata(client, data); i2c_set_clientdata(client, data);
mutex_init(&data->lock); mutex_init(&data->lock);
data->type = id->driver_data;
/* AD7418 has a curious behaviour on registers 6 and 7. They
* both always read 0xC071 and are not documented on the datasheet.
* We use them to detect the chip.
*/
if (kind <= 0) {
int reg, reg6, reg7;
/* the AD7416 lies within this address range, but I have
* no means to check.
*/
if (address >= 0x48 && address <= 0x4f) {
/* XXX add tests for AD7416 here */
/* data->type = ad7416; */
}
/* here we might have AD7417 or AD7418 */
else if (address >= 0x28 && address <= 0x2f) {
reg6 = i2c_smbus_read_word_data(client, 0x06);
reg7 = i2c_smbus_read_word_data(client, 0x07);
if (address == 0x28 && reg6 == 0xC071 && reg7 == 0xC071)
data->type = ad7418;
/* XXX add tests for AD7417 here */
/* both AD7417 and AD7418 have bits 0-5 of
* the CONF2 register at 0
*/
reg = i2c_smbus_read_byte_data(client,
AD7418_REG_CONF2);
if (reg & 0x3F)
data->type = any_chip; /* detection failed */
}
} else {
dev_dbg(&adapter->dev, "detection forced\n");
}
if (kind > 0)
data->type = kind;
else if (kind < 0 && data->type == any_chip) {
err = -ENODEV;
goto exit_free;
}
switch (data->type) { switch (data->type) {
case any_chip:
case ad7416: case ad7416:
data->adc_max = 0; data->adc_max = 0;
data->attrs.attrs = ad7416_attributes; data->attrs.attrs = ad7416_attributes;
strlcpy(client->name, "ad7416", I2C_NAME_SIZE);
break; break;
case ad7417: case ad7417:
data->adc_max = 4; data->adc_max = 4;
data->attrs.attrs = ad7417_attributes; data->attrs.attrs = ad7417_attributes;
strlcpy(client->name, "ad7417", I2C_NAME_SIZE);
break; break;
case ad7418: case ad7418:
data->adc_max = 1; data->adc_max = 1;
data->attrs.attrs = ad7418_attributes; data->attrs.attrs = ad7418_attributes;
strlcpy(client->name, "ad7418", I2C_NAME_SIZE);
break; break;
} }
if ((err = i2c_attach_client(client)))
goto exit_free;
dev_info(&client->dev, "%s chip found\n", client->name); dev_info(&client->dev, "%s chip found\n", client->name);
/* Initialize the AD7418 chip */ /* Initialize the AD7418 chip */
...@@ -324,7 +270,7 @@ static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -324,7 +270,7 @@ static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs))) if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs)))
goto exit_detach; goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev); data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -336,20 +282,17 @@ static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -336,20 +282,17 @@ static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove: exit_remove:
sysfs_remove_group(&client->dev.kobj, &data->attrs); sysfs_remove_group(&client->dev.kobj, &data->attrs);
exit_detach:
i2c_detach_client(client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int ad7418_detach_client(struct i2c_client *client) static int ad7418_remove(struct i2c_client *client)
{ {
struct ad7418_data *data = i2c_get_clientdata(client); struct ad7418_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &data->attrs); sysfs_remove_group(&client->dev.kobj, &data->attrs);
i2c_detach_client(client);
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -78,7 +78,6 @@ clearing it. Weird, ey? --Phil */ ...@@ -78,7 +78,6 @@ clearing it. Weird, ey? --Phil */
/* Each client has this additional data */ /* Each client has this additional data */
struct adm1021_data { struct adm1021_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
enum chips type; enum chips type;
...@@ -98,23 +97,42 @@ struct adm1021_data { ...@@ -98,23 +97,42 @@ struct adm1021_data {
u8 remote_temp_offset_prec; u8 remote_temp_offset_prec;
}; };
static int adm1021_attach_adapter(struct i2c_adapter *adapter); static int adm1021_probe(struct i2c_client *client,
static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int adm1021_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static void adm1021_init_client(struct i2c_client *client); static void adm1021_init_client(struct i2c_client *client);
static int adm1021_detach_client(struct i2c_client *client); static int adm1021_remove(struct i2c_client *client);
static struct adm1021_data *adm1021_update_device(struct device *dev); static struct adm1021_data *adm1021_update_device(struct device *dev);
/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */ /* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
static int read_only; static int read_only;
static const struct i2c_device_id adm1021_id[] = {
{ "adm1021", adm1021 },
{ "adm1023", adm1023 },
{ "max1617", max1617 },
{ "max1617a", max1617a },
{ "thmc10", thmc10 },
{ "lm84", lm84 },
{ "gl523sm", gl523sm },
{ "mc1066", mc1066 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adm1021_id);
/* This is the driver that will be inserted */ /* This is the driver that will be inserted */
static struct i2c_driver adm1021_driver = { static struct i2c_driver adm1021_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "adm1021", .name = "adm1021",
}, },
.attach_adapter = adm1021_attach_adapter, .probe = adm1021_probe,
.detach_client = adm1021_detach_client, .remove = adm1021_remove,
.id_table = adm1021_id,
.detect = adm1021_detect,
.address_data = &addr_data,
}; };
static ssize_t show_temp(struct device *dev, static ssize_t show_temp(struct device *dev,
...@@ -216,13 +234,6 @@ static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2); ...@@ -216,13 +234,6 @@ static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2);
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
static int adm1021_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, adm1021_detect);
}
static struct attribute *adm1021_attributes[] = { static struct attribute *adm1021_attributes[] = {
&sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp1_min.dev_attr.attr, &sensor_dev_attr_temp1_min.dev_attr.attr,
...@@ -243,36 +254,21 @@ static const struct attribute_group adm1021_group = { ...@@ -243,36 +254,21 @@ static const struct attribute_group adm1021_group = {
.attrs = adm1021_attributes, .attrs = adm1021_attributes,
}; };
static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) /* Return 0 if detection is successful, -ENODEV otherwise */
static int adm1021_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter;
int i; int i;
struct i2c_client *client;
struct adm1021_data *data;
int err = 0;
const char *type_name = ""; const char *type_name = "";
int conv_rate, status, config; int conv_rate, status, config;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
pr_debug("adm1021: detect failed, " pr_debug("adm1021: detect failed, "
"smbus byte data not supported!\n"); "smbus byte data not supported!\n");
goto error0; return -ENODEV;
}
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access adm1021 register values. */
if (!(data = kzalloc(sizeof(struct adm1021_data), GFP_KERNEL))) {
pr_debug("adm1021: detect failed, kzalloc failed!\n");
err = -ENOMEM;
goto error0;
} }
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &adm1021_driver;
status = i2c_smbus_read_byte_data(client, ADM1021_REG_STATUS); status = i2c_smbus_read_byte_data(client, ADM1021_REG_STATUS);
conv_rate = i2c_smbus_read_byte_data(client, conv_rate = i2c_smbus_read_byte_data(client,
ADM1021_REG_CONV_RATE_R); ADM1021_REG_CONV_RATE_R);
...@@ -284,8 +280,7 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -284,8 +280,7 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
|| (conv_rate & 0xF8) != 0x00) { || (conv_rate & 0xF8) != 0x00) {
pr_debug("adm1021: detect failed, " pr_debug("adm1021: detect failed, "
"chip not detected!\n"); "chip not detected!\n");
err = -ENODEV; return -ENODEV;
goto error1;
} }
} }
...@@ -336,24 +331,36 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -336,24 +331,36 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
type_name = "mc1066"; type_name = "mc1066";
} }
pr_debug("adm1021: Detected chip %s at adapter %d, address 0x%02x.\n", pr_debug("adm1021: Detected chip %s at adapter %d, address 0x%02x.\n",
type_name, i2c_adapter_id(adapter), address); type_name, i2c_adapter_id(adapter), client->addr);
strlcpy(info->type, type_name, I2C_NAME_SIZE);
/* Fill in the remaining client fields */ return 0;
strlcpy(client->name, type_name, I2C_NAME_SIZE); }
data->type = kind;
mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ static int adm1021_probe(struct i2c_client *client,
if ((err = i2c_attach_client(client))) const struct i2c_device_id *id)
goto error1; {
struct adm1021_data *data;
int err;
data = kzalloc(sizeof(struct adm1021_data), GFP_KERNEL);
if (!data) {
pr_debug("adm1021: detect failed, kzalloc failed!\n");
err = -ENOMEM;
goto error0;
}
i2c_set_clientdata(client, data);
data->type = id->driver_data;
mutex_init(&data->update_lock);
/* Initialize the ADM1021 chip */ /* Initialize the ADM1021 chip */
if (kind != lm84 && !read_only) if (data->type != lm84 && !read_only)
adm1021_init_client(client); adm1021_init_client(client);
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1021_group))) if ((err = sysfs_create_group(&client->dev.kobj, &adm1021_group)))
goto error2; goto error1;
data->hwmon_dev = hwmon_device_register(&client->dev); data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -365,8 +372,6 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -365,8 +372,6 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
error3: error3:
sysfs_remove_group(&client->dev.kobj, &adm1021_group); sysfs_remove_group(&client->dev.kobj, &adm1021_group);
error2:
i2c_detach_client(client);
error1: error1:
kfree(data); kfree(data);
error0: error0:
...@@ -382,17 +387,13 @@ static void adm1021_init_client(struct i2c_client *client) ...@@ -382,17 +387,13 @@ static void adm1021_init_client(struct i2c_client *client)
i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04); i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04);
} }
static int adm1021_detach_client(struct i2c_client *client) static int adm1021_remove(struct i2c_client *client)
{ {
struct adm1021_data *data = i2c_get_clientdata(client); struct adm1021_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &adm1021_group); sysfs_remove_group(&client->dev.kobj, &adm1021_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* adm1025.c * adm1025.c
* *
* Copyright (C) 2000 Chen-Yuan Wu <gwu@esoft.com> * Copyright (C) 2000 Chen-Yuan Wu <gwu@esoft.com>
* Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org> * Copyright (C) 2003-2008 Jean Delvare <khali@linux-fr.org>
* *
* The ADM1025 is a sensor chip made by Analog Devices. It reports up to 6 * The ADM1025 is a sensor chip made by Analog Devices. It reports up to 6
* voltages (including its own power source) and up to two temperatures * voltages (including its own power source) and up to two temperatures
...@@ -109,22 +109,35 @@ static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 }; ...@@ -109,22 +109,35 @@ static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 };
* Functions declaration * Functions declaration
*/ */
static int adm1025_attach_adapter(struct i2c_adapter *adapter); static int adm1025_probe(struct i2c_client *client,
static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int adm1025_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static void adm1025_init_client(struct i2c_client *client); static void adm1025_init_client(struct i2c_client *client);
static int adm1025_detach_client(struct i2c_client *client); static int adm1025_remove(struct i2c_client *client);
static struct adm1025_data *adm1025_update_device(struct device *dev); static struct adm1025_data *adm1025_update_device(struct device *dev);
/* /*
* Driver data (common to all clients) * Driver data (common to all clients)
*/ */
static const struct i2c_device_id adm1025_id[] = {
{ "adm1025", adm1025 },
{ "ne1619", ne1619 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adm1025_id);
static struct i2c_driver adm1025_driver = { static struct i2c_driver adm1025_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "adm1025", .name = "adm1025",
}, },
.attach_adapter = adm1025_attach_adapter, .probe = adm1025_probe,
.detach_client = adm1025_detach_client, .remove = adm1025_remove,
.id_table = adm1025_id,
.detect = adm1025_detect,
.address_data = &addr_data,
}; };
/* /*
...@@ -132,7 +145,6 @@ static struct i2c_driver adm1025_driver = { ...@@ -132,7 +145,6 @@ static struct i2c_driver adm1025_driver = {
*/ */
struct adm1025_data { struct adm1025_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
...@@ -344,13 +356,6 @@ static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); ...@@ -344,13 +356,6 @@ static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
* Real code * Real code
*/ */
static int adm1025_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, adm1025_detect);
}
static struct attribute *adm1025_attributes[] = { static struct attribute *adm1025_attributes[] = {
&sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr,
...@@ -403,31 +408,16 @@ static const struct attribute_group adm1025_group_in4 = { ...@@ -403,31 +408,16 @@ static const struct attribute_group adm1025_group_in4 = {
.attrs = adm1025_attributes_in4, .attrs = adm1025_attributes_in4,
}; };
/* /* Return 0 if detection is successful, -ENODEV otherwise */
* The following function does more than just detection. If detection static int adm1025_detect(struct i2c_client *client, int kind,
* succeeds, it also registers the new chip. struct i2c_board_info *info)
*/
static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
struct i2c_client *client; struct i2c_adapter *adapter = client->adapter;
struct adm1025_data *data;
int err = 0;
const char *name = ""; const char *name = "";
u8 config; u8 config;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit; return -ENODEV;
if (!(data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &adm1025_driver;
/* /*
* Now we do the remaining detection. A negative kind means that * Now we do the remaining detection. A negative kind means that
...@@ -448,8 +438,8 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -448,8 +438,8 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
ADM1025_REG_STATUS2) & 0xBC) != 0x00) { ADM1025_REG_STATUS2) & 0xBC) != 0x00) {
dev_dbg(&adapter->dev, dev_dbg(&adapter->dev,
"ADM1025 detection failed at 0x%02x.\n", "ADM1025 detection failed at 0x%02x.\n",
address); client->addr);
goto exit_free; return -ENODEV;
} }
} }
...@@ -465,7 +455,7 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -465,7 +455,7 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
} }
} else } else
if (man_id == 0xA1) { /* Philips */ if (man_id == 0xA1) { /* Philips */
if (address != 0x2E if (client->addr != 0x2E
&& (chip_id & 0xF0) == 0x20) { /* NE1619 */ && (chip_id & 0xF0) == 0x20) { /* NE1619 */
kind = ne1619; kind = ne1619;
} }
...@@ -475,7 +465,7 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -475,7 +465,7 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&adapter->dev, dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, " "Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X).\n", man_id, chip_id); "chip_id=0x%02X).\n", man_id, chip_id);
goto exit_free; return -ENODEV;
} }
} }
...@@ -484,23 +474,36 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -484,23 +474,36 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
} else if (kind == ne1619) { } else if (kind == ne1619) {
name = "ne1619"; name = "ne1619";
} }
strlcpy(info->type, name, I2C_NAME_SIZE);
/* We can fill in the remaining client fields */ return 0;
strlcpy(client->name, name, I2C_NAME_SIZE); }
mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ static int adm1025_probe(struct i2c_client *client,
if ((err = i2c_attach_client(client))) const struct i2c_device_id *id)
goto exit_free; {
struct adm1025_data *data;
int err;
u8 config;
data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
/* Initialize the ADM1025 chip */ /* Initialize the ADM1025 chip */
adm1025_init_client(client); adm1025_init_client(client);
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1025_group))) if ((err = sysfs_create_group(&client->dev.kobj, &adm1025_group)))
goto exit_detach; goto exit_free;
/* Pin 11 is either in4 (+12V) or VID4 */ /* Pin 11 is either in4 (+12V) or VID4 */
config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG);
if (!(config & 0x20)) { if (!(config & 0x20)) {
if ((err = sysfs_create_group(&client->dev.kobj, if ((err = sysfs_create_group(&client->dev.kobj,
&adm1025_group_in4))) &adm1025_group_in4)))
...@@ -518,8 +521,6 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -518,8 +521,6 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove: exit_remove:
sysfs_remove_group(&client->dev.kobj, &adm1025_group); sysfs_remove_group(&client->dev.kobj, &adm1025_group);
sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4);
exit_detach:
i2c_detach_client(client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
...@@ -568,18 +569,14 @@ static void adm1025_init_client(struct i2c_client *client) ...@@ -568,18 +569,14 @@ static void adm1025_init_client(struct i2c_client *client)
(reg&0x7E)|0x01); (reg&0x7E)|0x01);
} }
static int adm1025_detach_client(struct i2c_client *client) static int adm1025_remove(struct i2c_client *client)
{ {
struct adm1025_data *data = i2c_get_clientdata(client); struct adm1025_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &adm1025_group); sysfs_remove_group(&client->dev.kobj, &adm1025_group);
sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -259,7 +259,6 @@ struct pwm_data { ...@@ -259,7 +259,6 @@ struct pwm_data {
}; };
struct adm1026_data { struct adm1026_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
...@@ -293,10 +292,11 @@ struct adm1026_data { ...@@ -293,10 +292,11 @@ struct adm1026_data {
u8 config3; /* Register value */ u8 config3; /* Register value */
}; };
static int adm1026_attach_adapter(struct i2c_adapter *adapter); static int adm1026_probe(struct i2c_client *client,
static int adm1026_detect(struct i2c_adapter *adapter, int address, const struct i2c_device_id *id);
int kind); static int adm1026_detect(struct i2c_client *client, int kind,
static int adm1026_detach_client(struct i2c_client *client); struct i2c_board_info *info);
static int adm1026_remove(struct i2c_client *client);
static int adm1026_read_value(struct i2c_client *client, u8 reg); static int adm1026_read_value(struct i2c_client *client, u8 reg);
static int adm1026_write_value(struct i2c_client *client, u8 reg, int value); static int adm1026_write_value(struct i2c_client *client, u8 reg, int value);
static void adm1026_print_gpio(struct i2c_client *client); static void adm1026_print_gpio(struct i2c_client *client);
...@@ -305,22 +305,24 @@ static struct adm1026_data *adm1026_update_device(struct device *dev); ...@@ -305,22 +305,24 @@ static struct adm1026_data *adm1026_update_device(struct device *dev);
static void adm1026_init_client(struct i2c_client *client); static void adm1026_init_client(struct i2c_client *client);
static const struct i2c_device_id adm1026_id[] = {
{ "adm1026", adm1026 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adm1026_id);
static struct i2c_driver adm1026_driver = { static struct i2c_driver adm1026_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "adm1026", .name = "adm1026",
}, },
.attach_adapter = adm1026_attach_adapter, .probe = adm1026_probe,
.detach_client = adm1026_detach_client, .remove = adm1026_remove,
.id_table = adm1026_id,
.detect = adm1026_detect,
.address_data = &addr_data,
}; };
static int adm1026_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON)) {
return 0;
}
return i2c_probe(adapter, &addr_data, adm1026_detect);
}
static int adm1026_read_value(struct i2c_client *client, u8 reg) static int adm1026_read_value(struct i2c_client *client, u8 reg)
{ {
int res; int res;
...@@ -1647,48 +1649,32 @@ static const struct attribute_group adm1026_group_in8_9 = { ...@@ -1647,48 +1649,32 @@ static const struct attribute_group adm1026_group_in8_9 = {
.attrs = adm1026_attributes_in8_9, .attrs = adm1026_attributes_in8_9,
}; };
static int adm1026_detect(struct i2c_adapter *adapter, int address, /* Return 0 if detection is successful, -ENODEV otherwise */
int kind) static int adm1026_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter;
int address = client->addr;
int company, verstep; int company, verstep;
struct i2c_client *client;
struct adm1026_data *data;
int err = 0;
const char *type_name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
/* We need to be able to do byte I/O */ /* We need to be able to do byte I/O */
goto exit; return -ENODEV;
}; };
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access adm1026_{read,write}_value. */
if (!(data = kzalloc(sizeof(struct adm1026_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &adm1026_driver;
/* Now, we do the remaining detection. */ /* Now, we do the remaining detection. */
company = adm1026_read_value(client, ADM1026_REG_COMPANY); company = adm1026_read_value(client, ADM1026_REG_COMPANY);
verstep = adm1026_read_value(client, ADM1026_REG_VERSTEP); verstep = adm1026_read_value(client, ADM1026_REG_VERSTEP);
dev_dbg(&client->dev, "Detecting device at %d,0x%02x with" dev_dbg(&adapter->dev, "Detecting device at %d,0x%02x with"
" COMPANY: 0x%02x and VERSTEP: 0x%02x\n", " COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
i2c_adapter_id(client->adapter), client->addr, i2c_adapter_id(client->adapter), client->addr,
company, verstep); company, verstep);
/* If auto-detecting, Determine the chip type. */ /* If auto-detecting, Determine the chip type. */
if (kind <= 0) { if (kind <= 0) {
dev_dbg(&client->dev, "Autodetecting device at %d,0x%02x " dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x "
"...\n", i2c_adapter_id(adapter), address); "...\n", i2c_adapter_id(adapter), address);
if (company == ADM1026_COMPANY_ANALOG_DEV if (company == ADM1026_COMPANY_ANALOG_DEV
&& verstep == ADM1026_VERSTEP_ADM1026) { && verstep == ADM1026_VERSTEP_ADM1026) {
...@@ -1704,7 +1690,7 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, ...@@ -1704,7 +1690,7 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address,
verstep); verstep);
kind = any_chip; kind = any_chip;
} else { } else {
dev_dbg(&client->dev, ": Autodetection " dev_dbg(&adapter->dev, ": Autodetection "
"failed\n"); "failed\n");
/* Not an ADM1026 ... */ /* Not an ADM1026 ... */
if (kind == 0) { /* User used force=x,y */ if (kind == 0) { /* User used force=x,y */
...@@ -1713,33 +1699,29 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, ...@@ -1713,33 +1699,29 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address,
"force_adm1026.\n", "force_adm1026.\n",
i2c_adapter_id(adapter), address); i2c_adapter_id(adapter), address);
} }
goto exitfree; return -ENODEV;
} }
} }
strlcpy(info->type, "adm1026", I2C_NAME_SIZE);
/* Fill in the chip specific driver values */ return 0;
switch (kind) { }
case any_chip :
type_name = "adm1026"; static int adm1026_probe(struct i2c_client *client,
break; const struct i2c_device_id *id)
case adm1026 : {
type_name = "adm1026"; struct adm1026_data *data;
break; int err;
default :
dev_err(&adapter->dev, ": Internal error, invalid " data = kzalloc(sizeof(struct adm1026_data), GFP_KERNEL);
"kind (%d)!\n", kind); if (!data) {
err = -EFAULT; err = -ENOMEM;
goto exitfree; goto exit;
} }
strlcpy(client->name, type_name, I2C_NAME_SIZE);
/* Fill in the remaining client fields */ i2c_set_clientdata(client, data);
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(client)))
goto exitfree;
/* Set the VRM version */ /* Set the VRM version */
data->vrm = vid_which_vrm(); data->vrm = vid_which_vrm();
...@@ -1748,7 +1730,7 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, ...@@ -1748,7 +1730,7 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address,
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1026_group))) if ((err = sysfs_create_group(&client->dev.kobj, &adm1026_group)))
goto exitdetach; goto exitfree;
if (data->config1 & CFG1_AIN8_9) if (data->config1 & CFG1_AIN8_9)
err = sysfs_create_group(&client->dev.kobj, err = sysfs_create_group(&client->dev.kobj,
&adm1026_group_in8_9); &adm1026_group_in8_9);
...@@ -1773,15 +1755,13 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, ...@@ -1773,15 +1755,13 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address,
sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9); sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
else else
sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3); sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
exitdetach:
i2c_detach_client(client);
exitfree: exitfree:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int adm1026_detach_client(struct i2c_client *client) static int adm1026_remove(struct i2c_client *client)
{ {
struct adm1026_data *data = i2c_get_clientdata(client); struct adm1026_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
...@@ -1790,7 +1770,6 @@ static int adm1026_detach_client(struct i2c_client *client) ...@@ -1790,7 +1770,6 @@ static int adm1026_detach_client(struct i2c_client *client)
sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9); sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
else else
sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3); sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
i2c_detach_client(client);
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -115,9 +115,11 @@ static const u8 ADM1029_REG_FAN_DIV[] = { ...@@ -115,9 +115,11 @@ static const u8 ADM1029_REG_FAN_DIV[] = {
* Functions declaration * Functions declaration
*/ */
static int adm1029_attach_adapter(struct i2c_adapter *adapter); static int adm1029_probe(struct i2c_client *client,
static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int adm1029_detach_client(struct i2c_client *client); static int adm1029_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static int adm1029_remove(struct i2c_client *client);
static struct adm1029_data *adm1029_update_device(struct device *dev); static struct adm1029_data *adm1029_update_device(struct device *dev);
static int adm1029_init_client(struct i2c_client *client); static int adm1029_init_client(struct i2c_client *client);
...@@ -125,12 +127,22 @@ static int adm1029_init_client(struct i2c_client *client); ...@@ -125,12 +127,22 @@ static int adm1029_init_client(struct i2c_client *client);
* Driver data (common to all clients) * Driver data (common to all clients)
*/ */
static const struct i2c_device_id adm1029_id[] = {
{ "adm1029", adm1029 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adm1029_id);
static struct i2c_driver adm1029_driver = { static struct i2c_driver adm1029_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "adm1029", .name = "adm1029",
}, },
.attach_adapter = adm1029_attach_adapter, .probe = adm1029_probe,
.detach_client = adm1029_detach_client, .remove = adm1029_remove,
.id_table = adm1029_id,
.detect = adm1029_detect,
.address_data = &addr_data,
}; };
/* /*
...@@ -138,7 +150,6 @@ static struct i2c_driver adm1029_driver = { ...@@ -138,7 +150,6 @@ static struct i2c_driver adm1029_driver = {
*/ */
struct adm1029_data { struct adm1029_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
...@@ -284,37 +295,14 @@ static const struct attribute_group adm1029_group = { ...@@ -284,37 +295,14 @@ static const struct attribute_group adm1029_group = {
* Real code * Real code
*/ */
static int adm1029_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
static int adm1029_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
if (!(adapter->class & I2C_CLASS_HWMON)) struct i2c_adapter *adapter = client->adapter;
return 0;
return i2c_probe(adapter, &addr_data, adm1029_detect);
}
/*
* The following function does more than just detection. If detection
* succeeds, it also registers the new chip.
*/
static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *client;
struct adm1029_data *data;
int err = 0;
const char *name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit; return -ENODEV;
if (!(data = kzalloc(sizeof(struct adm1029_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &adm1029_driver;
/* Now we do the detection and identification. A negative kind /* Now we do the detection and identification. A negative kind
* means that the driver was loaded with no force parameter * means that the driver was loaded with no force parameter
...@@ -362,32 +350,41 @@ static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -362,32 +350,41 @@ static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind <= 0) { /* identification failed */ if (kind <= 0) { /* identification failed */
pr_debug("adm1029: Unsupported chip (man_id=0x%02X, " pr_debug("adm1029: Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X)\n", man_id, chip_id); "chip_id=0x%02X)\n", man_id, chip_id);
goto exit_free; return -ENODEV;
} }
} }
strlcpy(info->type, "adm1029", I2C_NAME_SIZE);
if (kind == adm1029) { return 0;
name = "adm1029"; }
static int adm1029_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct adm1029_data *data;
int err;
data = kzalloc(sizeof(struct adm1029_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
} }
/* We can fill in the remaining client fields */ i2c_set_clientdata(client, data);
strlcpy(client->name, name, I2C_NAME_SIZE);
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(client)))
goto exit_free;
/* /*
* Initialize the ADM1029 chip * Initialize the ADM1029 chip
* Check config register * Check config register
*/ */
if (adm1029_init_client(client) == 0) if (adm1029_init_client(client) == 0) {
goto exit_detach; err = -ENODEV;
goto exit_free;
}
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1029_group))) if ((err = sysfs_create_group(&client->dev.kobj, &adm1029_group)))
goto exit_detach; goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev); data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -399,8 +396,6 @@ static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -399,8 +396,6 @@ static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove_files: exit_remove_files:
sysfs_remove_group(&client->dev.kobj, &adm1029_group); sysfs_remove_group(&client->dev.kobj, &adm1029_group);
exit_detach:
i2c_detach_client(client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
...@@ -424,17 +419,13 @@ static int adm1029_init_client(struct i2c_client *client) ...@@ -424,17 +419,13 @@ static int adm1029_init_client(struct i2c_client *client)
return 1; return 1;
} }
static int adm1029_detach_client(struct i2c_client *client) static int adm1029_remove(struct i2c_client *client)
{ {
struct adm1029_data *data = i2c_get_clientdata(client); struct adm1029_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &adm1029_group); sysfs_remove_group(&client->dev.kobj, &adm1029_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -70,7 +70,6 @@ typedef u8 auto_chan_table_t[8][2]; ...@@ -70,7 +70,6 @@ typedef u8 auto_chan_table_t[8][2];
/* Each client has this additional data */ /* Each client has this additional data */
struct adm1031_data { struct adm1031_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
int chip_type; int chip_type;
...@@ -99,19 +98,32 @@ struct adm1031_data { ...@@ -99,19 +98,32 @@ struct adm1031_data {
s8 temp_crit[3]; s8 temp_crit[3];
}; };
static int adm1031_attach_adapter(struct i2c_adapter *adapter); static int adm1031_probe(struct i2c_client *client,
static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int adm1031_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static void adm1031_init_client(struct i2c_client *client); static void adm1031_init_client(struct i2c_client *client);
static int adm1031_detach_client(struct i2c_client *client); static int adm1031_remove(struct i2c_client *client);
static struct adm1031_data *adm1031_update_device(struct device *dev); static struct adm1031_data *adm1031_update_device(struct device *dev);
static const struct i2c_device_id adm1031_id[] = {
{ "adm1030", adm1030 },
{ "adm1031", adm1031 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adm1031_id);
/* This is the driver that will be inserted */ /* This is the driver that will be inserted */
static struct i2c_driver adm1031_driver = { static struct i2c_driver adm1031_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "adm1031", .name = "adm1031",
}, },
.attach_adapter = adm1031_attach_adapter, .probe = adm1031_probe,
.detach_client = adm1031_detach_client, .remove = adm1031_remove,
.id_table = adm1031_id,
.detect = adm1031_detect,
.address_data = &addr_data,
}; };
static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg) static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
...@@ -693,13 +705,6 @@ static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12); ...@@ -693,13 +705,6 @@ static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12);
static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13); static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13);
static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14);
static int adm1031_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, adm1031_detect);
}
static struct attribute *adm1031_attributes[] = { static struct attribute *adm1031_attributes[] = {
&sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_input.dev_attr.attr,
&sensor_dev_attr_fan1_div.dev_attr.attr, &sensor_dev_attr_fan1_div.dev_attr.attr,
...@@ -770,27 +775,15 @@ static const struct attribute_group adm1031_group_opt = { ...@@ -770,27 +775,15 @@ static const struct attribute_group adm1031_group_opt = {
.attrs = adm1031_attributes_opt, .attrs = adm1031_attributes_opt,
}; };
/* This function is called by i2c_probe */ /* Return 0 if detection is successful, -ENODEV otherwise */
static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) static int adm1031_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
struct i2c_client *client; struct i2c_adapter *adapter = client->adapter;
struct adm1031_data *data;
int err = 0;
const char *name = ""; const char *name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit; return -ENODEV;
if (!(data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &adm1031_driver;
if (kind < 0) { if (kind < 0) {
int id, co; int id, co;
...@@ -798,7 +791,7 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -798,7 +791,7 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
co = i2c_smbus_read_byte_data(client, 0x3e); co = i2c_smbus_read_byte_data(client, 0x3e);
if (!((id == 0x31 || id == 0x30) && co == 0x41)) if (!((id == 0x31 || id == 0x30) && co == 0x41))
goto exit_free; return -ENODEV;
kind = (id == 0x30) ? adm1030 : adm1031; kind = (id == 0x30) ? adm1030 : adm1031;
} }
...@@ -809,28 +802,43 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -809,28 +802,43 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
* auto fan control helper table. */ * auto fan control helper table. */
if (kind == adm1030) { if (kind == adm1030) {
name = "adm1030"; name = "adm1030";
data->chan_select_table = &auto_channel_select_table_adm1030;
} else if (kind == adm1031) { } else if (kind == adm1031) {
name = "adm1031"; name = "adm1031";
data->chan_select_table = &auto_channel_select_table_adm1031;
} }
data->chip_type = kind; strlcpy(info->type, name, I2C_NAME_SIZE);
strlcpy(client->name, name, I2C_NAME_SIZE); return 0;
}
static int adm1031_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct adm1031_data *data;
int err;
data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
data->chip_type = id->driver_data;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ if (data->chip_type == adm1030)
if ((err = i2c_attach_client(client))) data->chan_select_table = &auto_channel_select_table_adm1030;
goto exit_free; else
data->chan_select_table = &auto_channel_select_table_adm1031;
/* Initialize the ADM1031 chip */ /* Initialize the ADM1031 chip */
adm1031_init_client(client); adm1031_init_client(client);
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group))) if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group)))
goto exit_detach; goto exit_free;
if (kind == adm1031) { if (data->chip_type == adm1031) {
if ((err = sysfs_create_group(&client->dev.kobj, if ((err = sysfs_create_group(&client->dev.kobj,
&adm1031_group_opt))) &adm1031_group_opt)))
goto exit_remove; goto exit_remove;
...@@ -847,25 +855,19 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -847,25 +855,19 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove: exit_remove:
sysfs_remove_group(&client->dev.kobj, &adm1031_group); sysfs_remove_group(&client->dev.kobj, &adm1031_group);
sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
exit_detach:
i2c_detach_client(client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int adm1031_detach_client(struct i2c_client *client) static int adm1031_remove(struct i2c_client *client)
{ {
struct adm1031_data *data = i2c_get_clientdata(client); struct adm1031_data *data = i2c_get_clientdata(client);
int ret;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &adm1031_group); sysfs_remove_group(&client->dev.kobj, &adm1031_group);
sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
if ((ret = i2c_detach_client(client)) != 0) {
return ret;
}
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -130,25 +130,37 @@ static inline unsigned int AOUT_FROM_REG(u8 reg) ...@@ -130,25 +130,37 @@ static inline unsigned int AOUT_FROM_REG(u8 reg)
return SCALE(reg, 1250, 255); return SCALE(reg, 1250, 255);
} }
static int adm9240_attach_adapter(struct i2c_adapter *adapter); static int adm9240_probe(struct i2c_client *client,
static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int adm9240_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static void adm9240_init_client(struct i2c_client *client); static void adm9240_init_client(struct i2c_client *client);
static int adm9240_detach_client(struct i2c_client *client); static int adm9240_remove(struct i2c_client *client);
static struct adm9240_data *adm9240_update_device(struct device *dev); static struct adm9240_data *adm9240_update_device(struct device *dev);
/* driver data */ /* driver data */
static const struct i2c_device_id adm9240_id[] = {
{ "adm9240", adm9240 },
{ "ds1780", ds1780 },
{ "lm81", lm81 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adm9240_id);
static struct i2c_driver adm9240_driver = { static struct i2c_driver adm9240_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "adm9240", .name = "adm9240",
}, },
.attach_adapter = adm9240_attach_adapter, .probe = adm9240_probe,
.detach_client = adm9240_detach_client, .remove = adm9240_remove,
.id_table = adm9240_id,
.detect = adm9240_detect,
.address_data = &addr_data,
}; };
/* per client data */ /* per client data */
struct adm9240_data { struct adm9240_data {
enum chips type;
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
char valid; char valid;
...@@ -532,28 +544,17 @@ static const struct attribute_group adm9240_group = { ...@@ -532,28 +544,17 @@ static const struct attribute_group adm9240_group = {
/*** sensor chip detect and driver install ***/ /*** sensor chip detect and driver install ***/
static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind) /* Return 0 if detection is successful, -ENODEV otherwise */
static int adm9240_detect(struct i2c_client *new_client, int kind,
struct i2c_board_info *info)
{ {
struct i2c_client *new_client; struct i2c_adapter *adapter = new_client->adapter;
struct adm9240_data *data;
int err = 0;
const char *name = ""; const char *name = "";
int address = new_client->addr;
u8 man_id, die_rev; u8 man_id, die_rev;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit; return -ENODEV;
if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &adm9240_driver;
new_client->flags = 0;
if (kind == 0) { if (kind == 0) {
kind = adm9240; kind = adm9240;
...@@ -566,7 +567,7 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -566,7 +567,7 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
!= address) { != address) {
dev_err(&adapter->dev, "detect fail: address match, " dev_err(&adapter->dev, "detect fail: address match, "
"0x%02x\n", address); "0x%02x\n", address);
goto exit_free; return -ENODEV;
} }
/* check known chip manufacturer */ /* check known chip manufacturer */
...@@ -581,7 +582,7 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -581,7 +582,7 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
} else { } else {
dev_err(&adapter->dev, "detect fail: unknown manuf, " dev_err(&adapter->dev, "detect fail: unknown manuf, "
"0x%02x\n", man_id); "0x%02x\n", man_id);
goto exit_free; return -ENODEV;
} }
/* successful detect, print chip info */ /* successful detect, print chip info */
...@@ -600,20 +601,31 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -600,20 +601,31 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
} else if (kind == lm81) { } else if (kind == lm81) {
name = "lm81"; name = "lm81";
} }
strlcpy(info->type, name, I2C_NAME_SIZE);
/* fill in the remaining client fields and attach */ return 0;
strlcpy(new_client->name, name, I2C_NAME_SIZE); }
data->type = kind;
mutex_init(&data->update_lock);
if ((err = i2c_attach_client(new_client))) static int adm9240_probe(struct i2c_client *new_client,
goto exit_free; const struct i2c_device_id *id)
{
struct adm9240_data *data;
int err;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(new_client, data);
mutex_init(&data->update_lock);
adm9240_init_client(new_client); adm9240_init_client(new_client);
/* populate sysfs filesystem */ /* populate sysfs filesystem */
if ((err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group))) if ((err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group)))
goto exit_detach; goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev); data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -625,32 +637,19 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -625,32 +637,19 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove: exit_remove:
sysfs_remove_group(&new_client->dev.kobj, &adm9240_group); sysfs_remove_group(&new_client->dev.kobj, &adm9240_group);
exit_detach:
i2c_detach_client(new_client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int adm9240_attach_adapter(struct i2c_adapter *adapter) static int adm9240_remove(struct i2c_client *client)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, adm9240_detect);
}
static int adm9240_detach_client(struct i2c_client *client)
{ {
struct adm9240_data *data = i2c_get_clientdata(client); struct adm9240_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &adm9240_group); sysfs_remove_group(&client->dev.kobj, &adm9240_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -64,7 +64,6 @@ static unsigned int ads7828_lsb_resol; /* resolution of the ADC sample lsb */ ...@@ -64,7 +64,6 @@ static unsigned int ads7828_lsb_resol; /* resolution of the ADC sample lsb */
/* Each client has this additional data */ /* Each client has this additional data */
struct ads7828_data { struct ads7828_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; /* mutex protect updates */ struct mutex update_lock; /* mutex protect updates */
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
...@@ -73,7 +72,10 @@ struct ads7828_data { ...@@ -73,7 +72,10 @@ struct ads7828_data {
}; };
/* Function declaration - necessary due to function dependencies */ /* Function declaration - necessary due to function dependencies */
static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind); static int ads7828_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static int ads7828_probe(struct i2c_client *client,
const struct i2c_device_id *id);
/* The ADS7828 returns the 12-bit sample in two bytes, /* The ADS7828 returns the 12-bit sample in two bytes,
these are read as a word then byte-swapped */ these are read as a word then byte-swapped */
...@@ -156,58 +158,43 @@ static const struct attribute_group ads7828_group = { ...@@ -156,58 +158,43 @@ static const struct attribute_group ads7828_group = {
.attrs = ads7828_attributes, .attrs = ads7828_attributes,
}; };
static int ads7828_attach_adapter(struct i2c_adapter *adapter) static int ads7828_remove(struct i2c_client *client)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, ads7828_detect);
}
static int ads7828_detach_client(struct i2c_client *client)
{ {
struct ads7828_data *data = i2c_get_clientdata(client); struct ads7828_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &ads7828_group); sysfs_remove_group(&client->dev.kobj, &ads7828_group);
i2c_detach_client(client);
kfree(i2c_get_clientdata(client)); kfree(i2c_get_clientdata(client));
return 0; return 0;
} }
static const struct i2c_device_id ads7828_id[] = {
{ "ads7828", ads7828 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ads7828_id);
/* This is the driver that will be inserted */ /* This is the driver that will be inserted */
static struct i2c_driver ads7828_driver = { static struct i2c_driver ads7828_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "ads7828", .name = "ads7828",
}, },
.attach_adapter = ads7828_attach_adapter, .probe = ads7828_probe,
.detach_client = ads7828_detach_client, .remove = ads7828_remove,
.id_table = ads7828_id,
.detect = ads7828_detect,
.address_data = &addr_data,
}; };
/* This function is called by i2c_probe */ /* Return 0 if detection is successful, -ENODEV otherwise */
static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind) static int ads7828_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
struct i2c_client *client; struct i2c_adapter *adapter = client->adapter;
struct ads7828_data *data;
int err = 0;
const char *name = "";
/* Check we have a valid client */ /* Check we have a valid client */
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA))
goto exit; return -ENODEV;
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access ads7828_read_value. */
data = kzalloc(sizeof(struct ads7828_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &ads7828_driver;
/* Now, we do the remaining detection. There is no identification /* Now, we do the remaining detection. There is no identification
dedicated register so attempt to sanity check using knowledge of dedicated register so attempt to sanity check using knowledge of
...@@ -225,32 +212,34 @@ static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -225,32 +212,34 @@ static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind)
printk(KERN_DEBUG printk(KERN_DEBUG
"%s : Doesn't look like an ads7828 device\n", "%s : Doesn't look like an ads7828 device\n",
__func__); __func__);
goto exit_free; return -ENODEV;
} }
} }
} }
strlcpy(info->type, "ads7828", I2C_NAME_SIZE);
/* Determine the chip type - only one kind supported! */ return 0;
if (kind <= 0) }
kind = ads7828;
if (kind == ads7828) static int ads7828_probe(struct i2c_client *client,
name = "ads7828"; const struct i2c_device_id *id)
{
struct ads7828_data *data;
int err;
/* Fill in the remaining client fields, put it into the global list */ data = kzalloc(sizeof(struct ads7828_data), GFP_KERNEL);
strlcpy(client->name, name, I2C_NAME_SIZE); if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
err = i2c_attach_client(client);
if (err)
goto exit_free;
/* Register sysfs hooks */ /* Register sysfs hooks */
err = sysfs_create_group(&client->dev.kobj, &ads7828_group); err = sysfs_create_group(&client->dev.kobj, &ads7828_group);
if (err) if (err)
goto exit_detach; goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev); data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -262,8 +251,6 @@ static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -262,8 +251,6 @@ static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove: exit_remove:
sysfs_remove_group(&client->dev.kobj, &ads7828_group); sysfs_remove_group(&client->dev.kobj, &ads7828_group);
exit_detach:
i2c_detach_client(client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
......
...@@ -138,7 +138,6 @@ I2C_CLIENT_INSMOD_1(adt7470); ...@@ -138,7 +138,6 @@ I2C_CLIENT_INSMOD_1(adt7470);
#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID)
struct adt7470_data { struct adt7470_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct attribute_group attrs; struct attribute_group attrs;
struct mutex lock; struct mutex lock;
...@@ -164,16 +163,28 @@ struct adt7470_data { ...@@ -164,16 +163,28 @@ struct adt7470_data {
u8 pwm_auto_temp[ADT7470_PWM_COUNT]; u8 pwm_auto_temp[ADT7470_PWM_COUNT];
}; };
static int adt7470_attach_adapter(struct i2c_adapter *adapter); static int adt7470_probe(struct i2c_client *client,
static int adt7470_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int adt7470_detach_client(struct i2c_client *client); static int adt7470_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static int adt7470_remove(struct i2c_client *client);
static const struct i2c_device_id adt7470_id[] = {
{ "adt7470", adt7470 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adt7470_id);
static struct i2c_driver adt7470_driver = { static struct i2c_driver adt7470_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "adt7470", .name = "adt7470",
}, },
.attach_adapter = adt7470_attach_adapter, .probe = adt7470_probe,
.detach_client = adt7470_detach_client, .remove = adt7470_remove,
.id_table = adt7470_id,
.detect = adt7470_detect,
.address_data = &addr_data,
}; };
/* /*
...@@ -1004,64 +1015,52 @@ static struct attribute *adt7470_attr[] = ...@@ -1004,64 +1015,52 @@ static struct attribute *adt7470_attr[] =
NULL NULL
}; };
static int adt7470_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
{ static int adt7470_detect(struct i2c_client *client, int kind,
if (!(adapter->class & I2C_CLASS_HWMON)) struct i2c_board_info *info)
return 0;
return i2c_probe(adapter, &addr_data, adt7470_detect);
}
static int adt7470_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
struct i2c_client *client; struct i2c_adapter *adapter = client->adapter;
struct adt7470_data *data;
int err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit; return -ENODEV;
if (!(data = kzalloc(sizeof(struct adt7470_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
client->addr = address;
client->adapter = adapter;
client->driver = &adt7470_driver;
i2c_set_clientdata(client, data);
mutex_init(&data->lock);
if (kind <= 0) { if (kind <= 0) {
int vendor, device, revision; int vendor, device, revision;
vendor = i2c_smbus_read_byte_data(client, ADT7470_REG_VENDOR); vendor = i2c_smbus_read_byte_data(client, ADT7470_REG_VENDOR);
if (vendor != ADT7470_VENDOR) { if (vendor != ADT7470_VENDOR)
err = -ENODEV; return -ENODEV;
goto exit_free;
}
device = i2c_smbus_read_byte_data(client, ADT7470_REG_DEVICE); device = i2c_smbus_read_byte_data(client, ADT7470_REG_DEVICE);
if (device != ADT7470_DEVICE) { if (device != ADT7470_DEVICE)
err = -ENODEV; return -ENODEV;
goto exit_free;
}
revision = i2c_smbus_read_byte_data(client, revision = i2c_smbus_read_byte_data(client,
ADT7470_REG_REVISION); ADT7470_REG_REVISION);
if (revision != ADT7470_REVISION) { if (revision != ADT7470_REVISION)
err = -ENODEV; return -ENODEV;
goto exit_free;
}
} else } else
dev_dbg(&adapter->dev, "detection forced\n"); dev_dbg(&adapter->dev, "detection forced\n");
strlcpy(client->name, "adt7470", I2C_NAME_SIZE); strlcpy(info->type, "adt7470", I2C_NAME_SIZE);
if ((err = i2c_attach_client(client))) return 0;
goto exit_free; }
static int adt7470_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct adt7470_data *data;
int err;
data = kzalloc(sizeof(struct adt7470_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
mutex_init(&data->lock);
dev_info(&client->dev, "%s chip found\n", client->name); dev_info(&client->dev, "%s chip found\n", client->name);
...@@ -1071,7 +1070,7 @@ static int adt7470_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1071,7 +1070,7 @@ static int adt7470_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */ /* Register sysfs hooks */
data->attrs.attrs = adt7470_attr; data->attrs.attrs = adt7470_attr;
if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs))) if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs)))
goto exit_detach; goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev); data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -1083,21 +1082,18 @@ static int adt7470_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1083,21 +1082,18 @@ static int adt7470_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove: exit_remove:
sysfs_remove_group(&client->dev.kobj, &data->attrs); sysfs_remove_group(&client->dev.kobj, &data->attrs);
exit_detach:
i2c_detach_client(client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int adt7470_detach_client(struct i2c_client *client) static int adt7470_remove(struct i2c_client *client)
{ {
struct adt7470_data *data = i2c_get_clientdata(client); struct adt7470_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &data->attrs); sysfs_remove_group(&client->dev.kobj, &data->attrs);
i2c_detach_client(client);
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -143,7 +143,6 @@ I2C_CLIENT_INSMOD_1(adt7473); ...@@ -143,7 +143,6 @@ I2C_CLIENT_INSMOD_1(adt7473);
#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID)
struct adt7473_data { struct adt7473_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct attribute_group attrs; struct attribute_group attrs;
struct mutex lock; struct mutex lock;
...@@ -178,16 +177,28 @@ struct adt7473_data { ...@@ -178,16 +177,28 @@ struct adt7473_data {
u8 max_duty_at_overheat; u8 max_duty_at_overheat;
}; };
static int adt7473_attach_adapter(struct i2c_adapter *adapter); static int adt7473_probe(struct i2c_client *client,
static int adt7473_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int adt7473_detach_client(struct i2c_client *client); static int adt7473_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static int adt7473_remove(struct i2c_client *client);
static const struct i2c_device_id adt7473_id[] = {
{ "adt7473", adt7473 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adt7473_id);
static struct i2c_driver adt7473_driver = { static struct i2c_driver adt7473_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "adt7473", .name = "adt7473",
}, },
.attach_adapter = adt7473_attach_adapter, .probe = adt7473_probe,
.detach_client = adt7473_detach_client, .remove = adt7473_remove,
.id_table = adt7473_id,
.detect = adt7473_detect,
.address_data = &addr_data,
}; };
/* /*
...@@ -1042,66 +1053,52 @@ static struct attribute *adt7473_attr[] = ...@@ -1042,66 +1053,52 @@ static struct attribute *adt7473_attr[] =
NULL NULL
}; };
static int adt7473_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
static int adt7473_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
if (!(adapter->class & I2C_CLASS_HWMON)) struct i2c_adapter *adapter = client->adapter;
return 0;
return i2c_probe(adapter, &addr_data, adt7473_detect);
}
static int adt7473_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *client;
struct adt7473_data *data;
int err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit; return -ENODEV;
data = kzalloc(sizeof(struct adt7473_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
client->addr = address;
client->adapter = adapter;
client->driver = &adt7473_driver;
i2c_set_clientdata(client, data);
mutex_init(&data->lock);
if (kind <= 0) { if (kind <= 0) {
int vendor, device, revision; int vendor, device, revision;
vendor = i2c_smbus_read_byte_data(client, ADT7473_REG_VENDOR); vendor = i2c_smbus_read_byte_data(client, ADT7473_REG_VENDOR);
if (vendor != ADT7473_VENDOR) { if (vendor != ADT7473_VENDOR)
err = -ENODEV; return -ENODEV;
goto exit_free;
}
device = i2c_smbus_read_byte_data(client, ADT7473_REG_DEVICE); device = i2c_smbus_read_byte_data(client, ADT7473_REG_DEVICE);
if (device != ADT7473_DEVICE) { if (device != ADT7473_DEVICE)
err = -ENODEV; return -ENODEV;
goto exit_free;
}
revision = i2c_smbus_read_byte_data(client, revision = i2c_smbus_read_byte_data(client,
ADT7473_REG_REVISION); ADT7473_REG_REVISION);
if (revision != ADT7473_REV_68 && revision != ADT7473_REV_69) { if (revision != ADT7473_REV_68 && revision != ADT7473_REV_69)
err = -ENODEV; return -ENODEV;
goto exit_free;
}
} else } else
dev_dbg(&adapter->dev, "detection forced\n"); dev_dbg(&adapter->dev, "detection forced\n");
strlcpy(client->name, "adt7473", I2C_NAME_SIZE); strlcpy(info->type, "adt7473", I2C_NAME_SIZE);
err = i2c_attach_client(client); return 0;
if (err) }
goto exit_free;
static int adt7473_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct adt7473_data *data;
int err;
data = kzalloc(sizeof(struct adt7473_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
mutex_init(&data->lock);
dev_info(&client->dev, "%s chip found\n", client->name); dev_info(&client->dev, "%s chip found\n", client->name);
...@@ -1112,7 +1109,7 @@ static int adt7473_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1112,7 +1109,7 @@ static int adt7473_detect(struct i2c_adapter *adapter, int address, int kind)
data->attrs.attrs = adt7473_attr; data->attrs.attrs = adt7473_attr;
err = sysfs_create_group(&client->dev.kobj, &data->attrs); err = sysfs_create_group(&client->dev.kobj, &data->attrs);
if (err) if (err)
goto exit_detach; goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev); data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -1124,21 +1121,18 @@ static int adt7473_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1124,21 +1121,18 @@ static int adt7473_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove: exit_remove:
sysfs_remove_group(&client->dev.kobj, &data->attrs); sysfs_remove_group(&client->dev.kobj, &data->attrs);
exit_detach:
i2c_detach_client(client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int adt7473_detach_client(struct i2c_client *client) static int adt7473_remove(struct i2c_client *client)
{ {
struct adt7473_data *data = i2c_get_clientdata(client); struct adt7473_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &data->attrs); sysfs_remove_group(&client->dev.kobj, &data->attrs);
i2c_detach_client(client);
kfree(data); kfree(data);
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -46,21 +46,32 @@ static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END }; ...@@ -46,21 +46,32 @@ static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END };
I2C_CLIENT_INSMOD_1(atxp1); I2C_CLIENT_INSMOD_1(atxp1);
static int atxp1_attach_adapter(struct i2c_adapter * adapter); static int atxp1_probe(struct i2c_client *client,
static int atxp1_detach_client(struct i2c_client * client); const struct i2c_device_id *id);
static int atxp1_remove(struct i2c_client *client);
static struct atxp1_data * atxp1_update_device(struct device *dev); static struct atxp1_data * atxp1_update_device(struct device *dev);
static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind); static int atxp1_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static const struct i2c_device_id atxp1_id[] = {
{ "atxp1", atxp1 },
{ }
};
MODULE_DEVICE_TABLE(i2c, atxp1_id);
static struct i2c_driver atxp1_driver = { static struct i2c_driver atxp1_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "atxp1", .name = "atxp1",
}, },
.attach_adapter = atxp1_attach_adapter, .probe = atxp1_probe,
.detach_client = atxp1_detach_client, .remove = atxp1_remove,
.id_table = atxp1_id,
.detect = atxp1_detect,
.address_data = &addr_data,
}; };
struct atxp1_data { struct atxp1_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
unsigned long last_updated; unsigned long last_updated;
...@@ -263,35 +274,16 @@ static const struct attribute_group atxp1_group = { ...@@ -263,35 +274,16 @@ static const struct attribute_group atxp1_group = {
}; };
static int atxp1_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
static int atxp1_detect(struct i2c_client *new_client, int kind,
struct i2c_board_info *info)
{ {
if (!(adapter->class & I2C_CLASS_HWMON)) struct i2c_adapter *adapter = new_client->adapter;
return 0;
return i2c_probe(adapter, &addr_data, &atxp1_detect);
};
static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client * new_client;
struct atxp1_data * data;
int err = 0;
u8 temp; u8 temp;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit; return -ENODEV;
if (!(data = kzalloc(sizeof(struct atxp1_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &atxp1_driver;
new_client->flags = 0;
/* Detect ATXP1, checking if vendor ID registers are all zero */ /* Detect ATXP1, checking if vendor ID registers are all zero */
if (!((i2c_smbus_read_byte_data(new_client, 0x3e) == 0) && if (!((i2c_smbus_read_byte_data(new_client, 0x3e) == 0) &&
...@@ -305,35 +297,46 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -305,35 +297,46 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) && if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) &&
(i2c_smbus_read_byte_data(new_client, 0x11) == temp) )) (i2c_smbus_read_byte_data(new_client, 0x11) == temp) ))
goto exit_free; return -ENODEV;
} }
/* Get VRM */ /* Get VRM */
data->vrm = vid_which_vrm(); temp = vid_which_vrm();
if ((data->vrm != 90) && (data->vrm != 91)) { if ((temp != 90) && (temp != 91)) {
dev_err(&new_client->dev, "Not supporting VRM %d.%d\n", dev_err(&adapter->dev, "atxp1: Not supporting VRM %d.%d\n",
data->vrm / 10, data->vrm % 10); temp / 10, temp % 10);
goto exit_free; return -ENODEV;
} }
strncpy(new_client->name, "atxp1", I2C_NAME_SIZE); strlcpy(info->type, "atxp1", I2C_NAME_SIZE);
data->valid = 0;
mutex_init(&data->update_lock); return 0;
}
err = i2c_attach_client(new_client); static int atxp1_probe(struct i2c_client *new_client,
const struct i2c_device_id *id)
{
struct atxp1_data *data;
int err;
if (err) data = kzalloc(sizeof(struct atxp1_data), GFP_KERNEL);
{ if (!data) {
dev_err(&new_client->dev, "Attach client error.\n"); err = -ENOMEM;
goto exit_free; goto exit;
} }
/* Get VRM */
data->vrm = vid_which_vrm();
i2c_set_clientdata(new_client, data);
data->valid = 0;
mutex_init(&data->update_lock);
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group))) if ((err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group)))
goto exit_detach; goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev); data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -348,30 +351,22 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -348,30 +351,22 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove_files: exit_remove_files:
sysfs_remove_group(&new_client->dev.kobj, &atxp1_group); sysfs_remove_group(&new_client->dev.kobj, &atxp1_group);
exit_detach:
i2c_detach_client(new_client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
}; };
static int atxp1_detach_client(struct i2c_client * client) static int atxp1_remove(struct i2c_client *client)
{ {
struct atxp1_data * data = i2c_get_clientdata(client); struct atxp1_data * data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &atxp1_group); sysfs_remove_group(&client->dev.kobj, &atxp1_group);
err = i2c_detach_client(client); kfree(data);
if (err)
dev_err(&client->dev, "Failed to detach client.\n");
else
kfree(data);
return err; return 0;
}; };
static int __init atxp1_init(void) static int __init atxp1_init(void)
......
...@@ -72,7 +72,6 @@ static const u8 DS1621_REG_TEMP[3] = { ...@@ -72,7 +72,6 @@ static const u8 DS1621_REG_TEMP[3] = {
/* Each client has this additional data */ /* Each client has this additional data */
struct ds1621_data { struct ds1621_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
...@@ -82,20 +81,32 @@ struct ds1621_data { ...@@ -82,20 +81,32 @@ struct ds1621_data {
u8 conf; /* Register encoding, combined */ u8 conf; /* Register encoding, combined */
}; };
static int ds1621_attach_adapter(struct i2c_adapter *adapter); static int ds1621_probe(struct i2c_client *client,
static int ds1621_detect(struct i2c_adapter *adapter, int address, const struct i2c_device_id *id);
int kind); static int ds1621_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static void ds1621_init_client(struct i2c_client *client); static void ds1621_init_client(struct i2c_client *client);
static int ds1621_detach_client(struct i2c_client *client); static int ds1621_remove(struct i2c_client *client);
static struct ds1621_data *ds1621_update_client(struct device *dev); static struct ds1621_data *ds1621_update_client(struct device *dev);
static const struct i2c_device_id ds1621_id[] = {
{ "ds1621", ds1621 },
{ "ds1625", ds1621 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ds1621_id);
/* This is the driver that will be inserted */ /* This is the driver that will be inserted */
static struct i2c_driver ds1621_driver = { static struct i2c_driver ds1621_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "ds1621", .name = "ds1621",
}, },
.attach_adapter = ds1621_attach_adapter, .probe = ds1621_probe,
.detach_client = ds1621_detach_client, .remove = ds1621_remove,
.id_table = ds1621_id,
.detect = ds1621_detect,
.address_data = &addr_data,
}; };
/* All registers are word-sized, except for the configuration register. /* All registers are word-sized, except for the configuration register.
...@@ -199,40 +210,18 @@ static const struct attribute_group ds1621_group = { ...@@ -199,40 +210,18 @@ static const struct attribute_group ds1621_group = {
}; };
static int ds1621_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
{ static int ds1621_detect(struct i2c_client *client, int kind,
if (!(adapter->class & I2C_CLASS_HWMON)) struct i2c_board_info *info)
return 0;
return i2c_probe(adapter, &addr_data, ds1621_detect);
}
/* This function is called by i2c_probe */
static int ds1621_detect(struct i2c_adapter *adapter, int address,
int kind)
{ {
struct i2c_adapter *adapter = client->adapter;
int conf, temp; int conf, temp;
struct i2c_client *client; int i;
struct ds1621_data *data;
int i, err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_WORD_DATA
| I2C_FUNC_SMBUS_WRITE_BYTE)) | I2C_FUNC_SMBUS_WRITE_BYTE))
goto exit; return -ENODEV;
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access ds1621_{read,write}_value. */
if (!(data = kzalloc(sizeof(struct ds1621_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &ds1621_driver;
/* Now, we do the remaining detection. It is lousy. */ /* Now, we do the remaining detection. It is lousy. */
if (kind < 0) { if (kind < 0) {
...@@ -241,29 +230,41 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address, ...@@ -241,29 +230,41 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address,
improbable in our case. */ improbable in our case. */
conf = ds1621_read_value(client, DS1621_REG_CONF); conf = ds1621_read_value(client, DS1621_REG_CONF);
if (conf & DS1621_REG_CONFIG_NVB) if (conf & DS1621_REG_CONFIG_NVB)
goto exit_free; return -ENODEV;
/* The 7 lowest bits of a temperature should always be 0. */ /* The 7 lowest bits of a temperature should always be 0. */
for (i = 0; i < ARRAY_SIZE(data->temp); i++) { for (i = 0; i < ARRAY_SIZE(DS1621_REG_TEMP); i++) {
temp = ds1621_read_value(client, DS1621_REG_TEMP[i]); temp = ds1621_read_value(client, DS1621_REG_TEMP[i]);
if (temp & 0x007f) if (temp & 0x007f)
goto exit_free; return -ENODEV;
} }
} }
/* Fill in remaining client fields and put it into the global list */ strlcpy(info->type, "ds1621", I2C_NAME_SIZE);
strlcpy(client->name, "ds1621", I2C_NAME_SIZE);
mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ return 0;
if ((err = i2c_attach_client(client))) }
goto exit_free;
static int ds1621_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct ds1621_data *data;
int err;
data = kzalloc(sizeof(struct ds1621_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
/* Initialize the DS1621 chip */ /* Initialize the DS1621 chip */
ds1621_init_client(client); ds1621_init_client(client);
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &ds1621_group))) if ((err = sysfs_create_group(&client->dev.kobj, &ds1621_group)))
goto exit_detach; goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev); data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -275,25 +276,19 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address, ...@@ -275,25 +276,19 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address,
exit_remove_files: exit_remove_files:
sysfs_remove_group(&client->dev.kobj, &ds1621_group); sysfs_remove_group(&client->dev.kobj, &ds1621_group);
exit_detach:
i2c_detach_client(client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int ds1621_detach_client(struct i2c_client *client) static int ds1621_remove(struct i2c_client *client)
{ {
struct ds1621_data *data = i2c_get_clientdata(client); struct ds1621_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &ds1621_group); sysfs_remove_group(&client->dev.kobj, &ds1621_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
......
...@@ -87,7 +87,6 @@ I2C_CLIENT_INSMOD_2(f75373, f75375); ...@@ -87,7 +87,6 @@ I2C_CLIENT_INSMOD_2(f75373, f75375);
struct f75375_data { struct f75375_data {
unsigned short addr; unsigned short addr;
struct i2c_client *client;
struct device *hwmon_dev; struct device *hwmon_dev;
const char *name; const char *name;
...@@ -114,21 +113,12 @@ struct f75375_data { ...@@ -114,21 +113,12 @@ struct f75375_data {
s8 temp_max_hyst[2]; s8 temp_max_hyst[2];
}; };
static int f75375_attach_adapter(struct i2c_adapter *adapter); static int f75375_detect(struct i2c_client *client, int kind,
static int f75375_detect(struct i2c_adapter *adapter, int address, int kind); struct i2c_board_info *info);
static int f75375_detach_client(struct i2c_client *client);
static int f75375_probe(struct i2c_client *client, static int f75375_probe(struct i2c_client *client,
const struct i2c_device_id *id); const struct i2c_device_id *id);
static int f75375_remove(struct i2c_client *client); static int f75375_remove(struct i2c_client *client);
static struct i2c_driver f75375_legacy_driver = {
.driver = {
.name = "f75375_legacy",
},
.attach_adapter = f75375_attach_adapter,
.detach_client = f75375_detach_client,
};
static const struct i2c_device_id f75375_id[] = { static const struct i2c_device_id f75375_id[] = {
{ "f75373", f75373 }, { "f75373", f75373 },
{ "f75375", f75375 }, { "f75375", f75375 },
...@@ -137,12 +127,15 @@ static const struct i2c_device_id f75375_id[] = { ...@@ -137,12 +127,15 @@ static const struct i2c_device_id f75375_id[] = {
MODULE_DEVICE_TABLE(i2c, f75375_id); MODULE_DEVICE_TABLE(i2c, f75375_id);
static struct i2c_driver f75375_driver = { static struct i2c_driver f75375_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "f75375", .name = "f75375",
}, },
.probe = f75375_probe, .probe = f75375_probe,
.remove = f75375_remove, .remove = f75375_remove,
.id_table = f75375_id, .id_table = f75375_id,
.detect = f75375_detect,
.address_data = &addr_data,
}; };
static inline int f75375_read8(struct i2c_client *client, u8 reg) static inline int f75375_read8(struct i2c_client *client, u8 reg)
...@@ -607,22 +600,6 @@ static const struct attribute_group f75375_group = { ...@@ -607,22 +600,6 @@ static const struct attribute_group f75375_group = {
.attrs = f75375_attributes, .attrs = f75375_attributes,
}; };
static int f75375_detach_client(struct i2c_client *client)
{
int err;
f75375_remove(client);
err = i2c_detach_client(client);
if (err) {
dev_err(&client->dev,
"Client deregistration failed, "
"client not detached.\n");
return err;
}
kfree(client);
return 0;
}
static void f75375_init(struct i2c_client *client, struct f75375_data *data, static void f75375_init(struct i2c_client *client, struct f75375_data *data,
struct f75375s_platform_data *f75375s_pdata) struct f75375s_platform_data *f75375s_pdata)
{ {
...@@ -651,7 +628,6 @@ static int f75375_probe(struct i2c_client *client, ...@@ -651,7 +628,6 @@ static int f75375_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
i2c_set_clientdata(client, data); i2c_set_clientdata(client, data);
data->client = client;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
data->kind = id->driver_data; data->kind = id->driver_data;
...@@ -700,29 +676,13 @@ static int f75375_remove(struct i2c_client *client) ...@@ -700,29 +676,13 @@ static int f75375_remove(struct i2c_client *client)
return 0; return 0;
} }
static int f75375_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
{ static int f75375_detect(struct i2c_client *client, int kind,
if (!(adapter->class & I2C_CLASS_HWMON)) struct i2c_board_info *info)
return 0;
return i2c_probe(adapter, &addr_data, f75375_detect);
}
/* This function is called by i2c_probe */
static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
struct i2c_client *client; struct i2c_adapter *adapter = client->adapter;
u8 version = 0; u8 version = 0;
int err = 0;
const char *name = ""; const char *name = "";
struct i2c_device_id id;
if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client->addr = address;
client->adapter = adapter;
client->driver = &f75375_legacy_driver;
if (kind < 0) { if (kind < 0) {
u16 vendid = f75375_read16(client, F75375_REG_VENDOR); u16 vendid = f75375_read16(client, F75375_REG_VENDOR);
...@@ -736,7 +696,7 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -736,7 +696,7 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
dev_err(&adapter->dev, dev_err(&adapter->dev,
"failed,%02X,%02X,%02X\n", "failed,%02X,%02X,%02X\n",
chipid, version, vendid); chipid, version, vendid);
goto exit_free; return -ENODEV;
} }
} }
...@@ -746,43 +706,18 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -746,43 +706,18 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
name = "f75373"; name = "f75373";
} }
dev_info(&adapter->dev, "found %s version: %02X\n", name, version); dev_info(&adapter->dev, "found %s version: %02X\n", name, version);
strlcpy(client->name, name, I2C_NAME_SIZE); strlcpy(info->type, name, I2C_NAME_SIZE);
if ((err = i2c_attach_client(client)))
goto exit_free;
strlcpy(id.name, name, I2C_NAME_SIZE);
id.driver_data = kind;
if ((err = f75375_probe(client, &id)) < 0)
goto exit_detach;
return 0; return 0;
exit_detach:
i2c_detach_client(client);
exit_free:
kfree(client);
exit:
return err;
} }
static int __init sensors_f75375_init(void) static int __init sensors_f75375_init(void)
{ {
int status; return i2c_add_driver(&f75375_driver);
status = i2c_add_driver(&f75375_driver);
if (status)
return status;
status = i2c_add_driver(&f75375_legacy_driver);
if (status)
i2c_del_driver(&f75375_driver);
return status;
} }
static void __exit sensors_f75375_exit(void) static void __exit sensors_f75375_exit(void)
{ {
i2c_del_driver(&f75375_legacy_driver);
i2c_del_driver(&f75375_driver); i2c_del_driver(&f75375_driver);
} }
......
...@@ -106,9 +106,11 @@ I2C_CLIENT_INSMOD_1(fscher); ...@@ -106,9 +106,11 @@ I2C_CLIENT_INSMOD_1(fscher);
* Functions declaration * Functions declaration
*/ */
static int fscher_attach_adapter(struct i2c_adapter *adapter); static int fscher_probe(struct i2c_client *client,
static int fscher_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int fscher_detach_client(struct i2c_client *client); static int fscher_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static int fscher_remove(struct i2c_client *client);
static struct fscher_data *fscher_update_device(struct device *dev); static struct fscher_data *fscher_update_device(struct device *dev);
static void fscher_init_client(struct i2c_client *client); static void fscher_init_client(struct i2c_client *client);
...@@ -119,12 +121,21 @@ static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value); ...@@ -119,12 +121,21 @@ static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value);
* Driver data (common to all clients) * Driver data (common to all clients)
*/ */
static const struct i2c_device_id fscher_id[] = {
{ "fscher", fscher },
{ }
};
static struct i2c_driver fscher_driver = { static struct i2c_driver fscher_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "fscher", .name = "fscher",
}, },
.attach_adapter = fscher_attach_adapter, .probe = fscher_probe,
.detach_client = fscher_detach_client, .remove = fscher_remove,
.id_table = fscher_id,
.detect = fscher_detect,
.address_data = &addr_data,
}; };
/* /*
...@@ -132,7 +143,6 @@ static struct i2c_driver fscher_driver = { ...@@ -132,7 +143,6 @@ static struct i2c_driver fscher_driver = {
*/ */
struct fscher_data { struct fscher_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
...@@ -283,38 +293,14 @@ static const struct attribute_group fscher_group = { ...@@ -283,38 +293,14 @@ static const struct attribute_group fscher_group = {
* Real code * Real code
*/ */
static int fscher_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
{ static int fscher_detect(struct i2c_client *new_client, int kind,
if (!(adapter->class & I2C_CLASS_HWMON)) struct i2c_board_info *info)
return 0;
return i2c_probe(adapter, &addr_data, fscher_detect);
}
static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
struct i2c_client *new_client; struct i2c_adapter *adapter = new_client->adapter;
struct fscher_data *data;
int err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit; return -ENODEV;
/* OK. For now, we presume we have a valid client. We now create the
* client structure, even though we cannot fill it completely yet.
* But it allows us to access i2c_smbus_read_byte_data. */
if (!(data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
/* The common I2C client data is placed right before the
* Hermes-specific data. */
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &fscher_driver;
new_client->flags = 0;
/* Do the remaining detection unless force or force_fscher parameter */ /* Do the remaining detection unless force or force_fscher parameter */
if (kind < 0) { if (kind < 0) {
...@@ -324,24 +310,35 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -324,24 +310,35 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
FSCHER_REG_IDENT_1) != 0x45) /* 'E' */ FSCHER_REG_IDENT_1) != 0x45) /* 'E' */
|| (i2c_smbus_read_byte_data(new_client, || (i2c_smbus_read_byte_data(new_client,
FSCHER_REG_IDENT_2) != 0x52)) /* 'R' */ FSCHER_REG_IDENT_2) != 0x52)) /* 'R' */
goto exit_free; return -ENODEV;
}
strlcpy(info->type, "fscher", I2C_NAME_SIZE);
return 0;
}
static int fscher_probe(struct i2c_client *new_client,
const struct i2c_device_id *id)
{
struct fscher_data *data;
int err;
data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
} }
/* Fill in the remaining client fields and put it into the i2c_set_clientdata(new_client, data);
* global list */
strlcpy(new_client->name, "fscher", I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_free;
fscher_init_client(new_client); fscher_init_client(new_client);
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &fscher_group))) if ((err = sysfs_create_group(&new_client->dev.kobj, &fscher_group)))
goto exit_detach; goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev); data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -353,25 +350,19 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -353,25 +350,19 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove_files: exit_remove_files:
sysfs_remove_group(&new_client->dev.kobj, &fscher_group); sysfs_remove_group(&new_client->dev.kobj, &fscher_group);
exit_detach:
i2c_detach_client(new_client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int fscher_detach_client(struct i2c_client *client) static int fscher_remove(struct i2c_client *client)
{ {
struct fscher_data *data = i2c_get_clientdata(client); struct fscher_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &fscher_group); sysfs_remove_group(&client->dev.kobj, &fscher_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -171,20 +171,37 @@ static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 }; ...@@ -171,20 +171,37 @@ static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 };
* Functions declarations * Functions declarations
*/ */
static int fschmd_attach_adapter(struct i2c_adapter *adapter); static int fschmd_probe(struct i2c_client *client,
static int fschmd_detach_client(struct i2c_client *client); const struct i2c_device_id *id);
static int fschmd_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static int fschmd_remove(struct i2c_client *client);
static struct fschmd_data *fschmd_update_device(struct device *dev); static struct fschmd_data *fschmd_update_device(struct device *dev);
/* /*
* Driver data (common to all clients) * Driver data (common to all clients)
*/ */
static const struct i2c_device_id fschmd_id[] = {
{ "fscpos", fscpos },
{ "fscher", fscher },
{ "fscscy", fscscy },
{ "fschrc", fschrc },
{ "fschmd", fschmd },
{ }
};
MODULE_DEVICE_TABLE(i2c, fschmd_id);
static struct i2c_driver fschmd_driver = { static struct i2c_driver fschmd_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = FSCHMD_NAME, .name = FSCHMD_NAME,
}, },
.attach_adapter = fschmd_attach_adapter, .probe = fschmd_probe,
.detach_client = fschmd_detach_client, .remove = fschmd_remove,
.id_table = fschmd_id,
.detect = fschmd_detect,
.address_data = &addr_data,
}; };
/* /*
...@@ -192,7 +209,6 @@ static struct i2c_driver fschmd_driver = { ...@@ -192,7 +209,6 @@ static struct i2c_driver fschmd_driver = {
*/ */
struct fschmd_data { struct fschmd_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
int kind; int kind;
...@@ -269,7 +285,7 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute ...@@ -269,7 +285,7 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute
v = SENSORS_LIMIT(v, -128, 127) + 128; v = SENSORS_LIMIT(v, -128, 127) + 128;
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
i2c_smbus_write_byte_data(&data->client, i2c_smbus_write_byte_data(to_i2c_client(dev),
FSCHMD_REG_TEMP_LIMIT[data->kind][index], v); FSCHMD_REG_TEMP_LIMIT[data->kind][index], v);
data->temp_max[index] = v; data->temp_max[index] = v;
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
...@@ -346,14 +362,14 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute ...@@ -346,14 +362,14 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
reg = i2c_smbus_read_byte_data(&data->client, reg = i2c_smbus_read_byte_data(to_i2c_client(dev),
FSCHMD_REG_FAN_RIPPLE[data->kind][index]); FSCHMD_REG_FAN_RIPPLE[data->kind][index]);
/* bits 2..7 reserved => mask with 0x03 */ /* bits 2..7 reserved => mask with 0x03 */
reg &= ~0x03; reg &= ~0x03;
reg |= v; reg |= v;
i2c_smbus_write_byte_data(&data->client, i2c_smbus_write_byte_data(to_i2c_client(dev),
FSCHMD_REG_FAN_RIPPLE[data->kind][index], reg); FSCHMD_REG_FAN_RIPPLE[data->kind][index], reg);
data->fan_ripple[index] = reg; data->fan_ripple[index] = reg;
...@@ -416,7 +432,7 @@ static ssize_t store_pwm_auto_point1_pwm(struct device *dev, ...@@ -416,7 +432,7 @@ static ssize_t store_pwm_auto_point1_pwm(struct device *dev,
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
i2c_smbus_write_byte_data(&data->client, i2c_smbus_write_byte_data(to_i2c_client(dev),
FSCHMD_REG_FAN_MIN[data->kind][index], v); FSCHMD_REG_FAN_MIN[data->kind][index], v);
data->fan_min[index] = v; data->fan_min[index] = v;
...@@ -448,14 +464,14 @@ static ssize_t store_alert_led(struct device *dev, ...@@ -448,14 +464,14 @@ static ssize_t store_alert_led(struct device *dev,
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
reg = i2c_smbus_read_byte_data(&data->client, FSCHMD_REG_CONTROL); reg = i2c_smbus_read_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL);
if (v) if (v)
reg |= FSCHMD_CONTROL_ALERT_LED_MASK; reg |= FSCHMD_CONTROL_ALERT_LED_MASK;
else else
reg &= ~FSCHMD_CONTROL_ALERT_LED_MASK; reg &= ~FSCHMD_CONTROL_ALERT_LED_MASK;
i2c_smbus_write_byte_data(&data->client, FSCHMD_REG_CONTROL, reg); i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL, reg);
data->global_control = reg; data->global_control = reg;
...@@ -600,32 +616,15 @@ static void fschmd_dmi_decode(const struct dmi_header *header) ...@@ -600,32 +616,15 @@ static void fschmd_dmi_decode(const struct dmi_header *header)
} }
} }
static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) static int fschmd_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
struct i2c_client *client; struct i2c_adapter *adapter = client->adapter;
struct fschmd_data *data;
u8 revision;
const char * const names[5] = { "Poseidon", "Hermes", "Scylla",
"Heracles", "Heimdall" };
const char * const client_names[5] = { "fscpos", "fscher", "fscscy", const char * const client_names[5] = { "fscpos", "fscher", "fscscy",
"fschrc", "fschmd" }; "fschrc", "fschmd" };
int i, err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0; return -ENODEV;
/* OK. For now, we presume we have a valid client. We now create the
* client structure, even though we cannot fill it completely yet.
* But it allows us to access i2c_smbus_read_byte_data. */
if (!(data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL)))
return -ENOMEM;
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &fschmd_driver;
mutex_init(&data->update_lock);
/* Detect & Identify the chip */ /* Detect & Identify the chip */
if (kind <= 0) { if (kind <= 0) {
...@@ -650,9 +649,31 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -650,9 +649,31 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind)
else if (!strcmp(id, "HMD")) else if (!strcmp(id, "HMD"))
kind = fschmd; kind = fschmd;
else else
goto exit_free; return -ENODEV;
} }
strlcpy(info->type, client_names[kind - 1], I2C_NAME_SIZE);
return 0;
}
static int fschmd_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct fschmd_data *data;
u8 revision;
const char * const names[5] = { "Poseidon", "Hermes", "Scylla",
"Heracles", "Heimdall" };
int i, err;
enum chips kind = id->driver_data;
data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
if (kind == fscpos) { if (kind == fscpos) {
/* The Poseidon has hardwired temp limits, fill these /* The Poseidon has hardwired temp limits, fill these
in for the alarm resetting code */ in for the alarm resetting code */
...@@ -674,11 +695,6 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -674,11 +695,6 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind)
/* i2c kind goes from 1-5, we want from 0-4 to address arrays */ /* i2c kind goes from 1-5, we want from 0-4 to address arrays */
data->kind = kind - 1; data->kind = kind - 1;
strlcpy(client->name, client_names[data->kind], I2C_NAME_SIZE);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(client)))
goto exit_free;
for (i = 0; i < ARRAY_SIZE(fschmd_attr); i++) { for (i = 0; i < ARRAY_SIZE(fschmd_attr); i++) {
err = device_create_file(&client->dev, err = device_create_file(&client->dev,
...@@ -726,25 +742,14 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -726,25 +742,14 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind)
return 0; return 0;
exit_detach: exit_detach:
fschmd_detach_client(client); /* will also free data for us */ fschmd_remove(client); /* will also free data for us */
return err;
exit_free:
kfree(data);
return err; return err;
} }
static int fschmd_attach_adapter(struct i2c_adapter *adapter) static int fschmd_remove(struct i2c_client *client)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, fschmd_detect);
}
static int fschmd_detach_client(struct i2c_client *client)
{ {
struct fschmd_data *data = i2c_get_clientdata(client); struct fschmd_data *data = i2c_get_clientdata(client);
int i, err; int i;
/* Check if registered in case we're called from fschmd_detect /* Check if registered in case we're called from fschmd_detect
to cleanup after an error */ to cleanup after an error */
...@@ -760,9 +765,6 @@ static int fschmd_detach_client(struct i2c_client *client) ...@@ -760,9 +765,6 @@ static int fschmd_detach_client(struct i2c_client *client)
device_remove_file(&client->dev, device_remove_file(&client->dev,
&fschmd_fan_attr[i].dev_attr); &fschmd_fan_attr[i].dev_attr);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -87,9 +87,11 @@ static u8 FSCPOS_REG_TEMP_STATE[] = { 0x71, 0x81, 0x91 }; ...@@ -87,9 +87,11 @@ static u8 FSCPOS_REG_TEMP_STATE[] = { 0x71, 0x81, 0x91 };
/* /*
* Functions declaration * Functions declaration
*/ */
static int fscpos_attach_adapter(struct i2c_adapter *adapter); static int fscpos_probe(struct i2c_client *client,
static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int fscpos_detach_client(struct i2c_client *client); static int fscpos_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static int fscpos_remove(struct i2c_client *client);
static int fscpos_read_value(struct i2c_client *client, u8 reg); static int fscpos_read_value(struct i2c_client *client, u8 reg);
static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value); static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value);
...@@ -101,19 +103,27 @@ static void reset_fan_alarm(struct i2c_client *client, int nr); ...@@ -101,19 +103,27 @@ static void reset_fan_alarm(struct i2c_client *client, int nr);
/* /*
* Driver data (common to all clients) * Driver data (common to all clients)
*/ */
static const struct i2c_device_id fscpos_id[] = {
{ "fscpos", fscpos },
{ }
};
static struct i2c_driver fscpos_driver = { static struct i2c_driver fscpos_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "fscpos", .name = "fscpos",
}, },
.attach_adapter = fscpos_attach_adapter, .probe = fscpos_probe,
.detach_client = fscpos_detach_client, .remove = fscpos_remove,
.id_table = fscpos_id,
.detect = fscpos_detect,
.address_data = &addr_data,
}; };
/* /*
* Client data (each client gets its own) * Client data (each client gets its own)
*/ */
struct fscpos_data { struct fscpos_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
char valid; /* 0 until following fields are valid */ char valid; /* 0 until following fields are valid */
...@@ -470,39 +480,14 @@ static const struct attribute_group fscpos_group = { ...@@ -470,39 +480,14 @@ static const struct attribute_group fscpos_group = {
.attrs = fscpos_attributes, .attrs = fscpos_attributes,
}; };
static int fscpos_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
{ static int fscpos_detect(struct i2c_client *new_client, int kind,
if (!(adapter->class & I2C_CLASS_HWMON)) struct i2c_board_info *info)
return 0;
return i2c_probe(adapter, &addr_data, fscpos_detect);
}
static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
struct i2c_client *new_client; struct i2c_adapter *adapter = new_client->adapter;
struct fscpos_data *data;
int err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit; return -ENODEV;
/*
* OK. For now, we presume we have a valid client. We now create the
* client structure, even though we cannot fill it completely yet.
* But it allows us to access fscpos_{read,write}_value.
*/
if (!(data = kzalloc(sizeof(struct fscpos_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &fscpos_driver;
new_client->flags = 0;
/* Do the remaining detection unless force or force_fscpos parameter */ /* Do the remaining detection unless force or force_fscpos parameter */
if (kind < 0) { if (kind < 0) {
...@@ -512,22 +497,30 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -512,22 +497,30 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
!= 0x45) /* 'E' */ != 0x45) /* 'E' */
|| (fscpos_read_value(new_client, FSCPOS_REG_IDENT_2) || (fscpos_read_value(new_client, FSCPOS_REG_IDENT_2)
!= 0x47))/* 'G' */ != 0x47))/* 'G' */
{ return -ENODEV;
dev_dbg(&new_client->dev, "fscpos detection failed\n");
goto exit_free;
}
} }
/* Fill in the remaining client fields and put it in the global list */ strlcpy(info->type, "fscpos", I2C_NAME_SIZE);
strlcpy(new_client->name, "fscpos", I2C_NAME_SIZE);
return 0;
}
static int fscpos_probe(struct i2c_client *new_client,
const struct i2c_device_id *id)
{
struct fscpos_data *data;
int err;
data = kzalloc(sizeof(struct fscpos_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(new_client, data);
data->valid = 0; data->valid = 0;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_free;
/* Inizialize the fscpos chip */ /* Inizialize the fscpos chip */
fscpos_init_client(new_client); fscpos_init_client(new_client);
...@@ -536,7 +529,7 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -536,7 +529,7 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &fscpos_group))) if ((err = sysfs_create_group(&new_client->dev.kobj, &fscpos_group)))
goto exit_detach; goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev); data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -548,24 +541,19 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -548,24 +541,19 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove_files: exit_remove_files:
sysfs_remove_group(&new_client->dev.kobj, &fscpos_group); sysfs_remove_group(&new_client->dev.kobj, &fscpos_group);
exit_detach:
i2c_detach_client(new_client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int fscpos_detach_client(struct i2c_client *client) static int fscpos_remove(struct i2c_client *client)
{ {
struct fscpos_data *data = i2c_get_clientdata(client); struct fscpos_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &fscpos_group); sysfs_remove_group(&client->dev.kobj, &fscpos_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -114,7 +114,6 @@ static inline u8 FAN_TO_REG(long rpm, int div) ...@@ -114,7 +114,6 @@ static inline u8 FAN_TO_REG(long rpm, int div)
/* Each client has this additional data */ /* Each client has this additional data */
struct gl518_data { struct gl518_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
enum chips type; enum chips type;
...@@ -138,21 +137,33 @@ struct gl518_data { ...@@ -138,21 +137,33 @@ struct gl518_data {
u8 beep_enable; /* Boolean */ u8 beep_enable; /* Boolean */
}; };
static int gl518_attach_adapter(struct i2c_adapter *adapter); static int gl518_probe(struct i2c_client *client,
static int gl518_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int gl518_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static void gl518_init_client(struct i2c_client *client); static void gl518_init_client(struct i2c_client *client);
static int gl518_detach_client(struct i2c_client *client); static int gl518_remove(struct i2c_client *client);
static int gl518_read_value(struct i2c_client *client, u8 reg); static int gl518_read_value(struct i2c_client *client, u8 reg);
static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value); static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value);
static struct gl518_data *gl518_update_device(struct device *dev); static struct gl518_data *gl518_update_device(struct device *dev);
static const struct i2c_device_id gl518_id[] = {
{ "gl518sm", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, gl518_id);
/* This is the driver that will be inserted */ /* This is the driver that will be inserted */
static struct i2c_driver gl518_driver = { static struct i2c_driver gl518_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "gl518sm", .name = "gl518sm",
}, },
.attach_adapter = gl518_attach_adapter, .probe = gl518_probe,
.detach_client = gl518_detach_client, .remove = gl518_remove,
.id_table = gl518_id,
.detect = gl518_detect,
.address_data = &addr_data,
}; };
/* /*
...@@ -472,46 +483,23 @@ static const struct attribute_group gl518_group_r80 = { ...@@ -472,46 +483,23 @@ static const struct attribute_group gl518_group_r80 = {
* Real code * Real code
*/ */
static int gl518_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
{ static int gl518_detect(struct i2c_client *client, int kind,
if (!(adapter->class & I2C_CLASS_HWMON)) struct i2c_board_info *info)
return 0;
return i2c_probe(adapter, &addr_data, gl518_detect);
}
static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
struct i2c_adapter *adapter = client->adapter;
int i; int i;
struct i2c_client *client;
struct gl518_data *data;
int err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA)) I2C_FUNC_SMBUS_WORD_DATA))
goto exit; return -ENODEV;
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access gl518_{read,write}_value. */
if (!(data = kzalloc(sizeof(struct gl518_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &gl518_driver;
/* Now, we do the remaining detection. */ /* Now, we do the remaining detection. */
if (kind < 0) { if (kind < 0) {
if ((gl518_read_value(client, GL518_REG_CHIP_ID) != 0x80) if ((gl518_read_value(client, GL518_REG_CHIP_ID) != 0x80)
|| (gl518_read_value(client, GL518_REG_CONF) & 0x80)) || (gl518_read_value(client, GL518_REG_CONF) & 0x80))
goto exit_free; return -ENODEV;
} }
/* Determine the chip type. */ /* Determine the chip type. */
...@@ -526,19 +514,32 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -526,19 +514,32 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&adapter->dev, dev_info(&adapter->dev,
"Ignoring 'force' parameter for unknown " "Ignoring 'force' parameter for unknown "
"chip at adapter %d, address 0x%02x\n", "chip at adapter %d, address 0x%02x\n",
i2c_adapter_id(adapter), address); i2c_adapter_id(adapter), client->addr);
goto exit_free; return -ENODEV;
} }
} }
/* Fill in the remaining client fields */ strlcpy(info->type, "gl518sm", I2C_NAME_SIZE);
strlcpy(client->name, "gl518sm", I2C_NAME_SIZE);
data->type = kind;
mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ return 0;
if ((err = i2c_attach_client(client))) }
goto exit_free;
static int gl518_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct gl518_data *data;
int err, revision;
data = kzalloc(sizeof(struct gl518_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
revision = gl518_read_value(client, GL518_REG_REVISION);
data->type = revision == 0x80 ? gl518sm_r80 : gl518sm_r00;
mutex_init(&data->update_lock);
/* Initialize the GL518SM chip */ /* Initialize the GL518SM chip */
data->alarm_mask = 0xff; data->alarm_mask = 0xff;
...@@ -546,7 +547,7 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -546,7 +547,7 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &gl518_group))) if ((err = sysfs_create_group(&client->dev.kobj, &gl518_group)))
goto exit_detach; goto exit_free;
if (data->type == gl518sm_r80) if (data->type == gl518sm_r80)
if ((err = sysfs_create_group(&client->dev.kobj, if ((err = sysfs_create_group(&client->dev.kobj,
&gl518_group_r80))) &gl518_group_r80)))
...@@ -564,8 +565,6 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -564,8 +565,6 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
sysfs_remove_group(&client->dev.kobj, &gl518_group); sysfs_remove_group(&client->dev.kobj, &gl518_group);
if (data->type == gl518sm_r80) if (data->type == gl518sm_r80)
sysfs_remove_group(&client->dev.kobj, &gl518_group_r80); sysfs_remove_group(&client->dev.kobj, &gl518_group_r80);
exit_detach:
i2c_detach_client(client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
...@@ -591,19 +590,15 @@ static void gl518_init_client(struct i2c_client *client) ...@@ -591,19 +590,15 @@ static void gl518_init_client(struct i2c_client *client)
gl518_write_value(client, GL518_REG_CONF, 0x40 | regvalue); gl518_write_value(client, GL518_REG_CONF, 0x40 | regvalue);
} }
static int gl518_detach_client(struct i2c_client *client) static int gl518_remove(struct i2c_client *client)
{ {
struct gl518_data *data = i2c_get_clientdata(client); struct gl518_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &gl518_group); sysfs_remove_group(&client->dev.kobj, &gl518_group);
if (data->type == gl518sm_r80) if (data->type == gl518sm_r80)
sysfs_remove_group(&client->dev.kobj, &gl518_group_r80); sysfs_remove_group(&client->dev.kobj, &gl518_group_r80);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -79,26 +79,37 @@ static const u8 GL520_REG_TEMP_MAX_HYST[] = { 0x06, 0x18 }; ...@@ -79,26 +79,37 @@ static const u8 GL520_REG_TEMP_MAX_HYST[] = { 0x06, 0x18 };
* Function declarations * Function declarations
*/ */
static int gl520_attach_adapter(struct i2c_adapter *adapter); static int gl520_probe(struct i2c_client *client,
static int gl520_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int gl520_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static void gl520_init_client(struct i2c_client *client); static void gl520_init_client(struct i2c_client *client);
static int gl520_detach_client(struct i2c_client *client); static int gl520_remove(struct i2c_client *client);
static int gl520_read_value(struct i2c_client *client, u8 reg); static int gl520_read_value(struct i2c_client *client, u8 reg);
static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value); static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value);
static struct gl520_data *gl520_update_device(struct device *dev); static struct gl520_data *gl520_update_device(struct device *dev);
/* Driver data */ /* Driver data */
static const struct i2c_device_id gl520_id[] = {
{ "gl520sm", gl520sm },
{ }
};
MODULE_DEVICE_TABLE(i2c, gl520_id);
static struct i2c_driver gl520_driver = { static struct i2c_driver gl520_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "gl520sm", .name = "gl520sm",
}, },
.attach_adapter = gl520_attach_adapter, .probe = gl520_probe,
.detach_client = gl520_detach_client, .remove = gl520_remove,
.id_table = gl520_id,
.detect = gl520_detect,
.address_data = &addr_data,
}; };
/* Client data */ /* Client data */
struct gl520_data { struct gl520_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
char valid; /* zero until the following fields are valid */ char valid; /* zero until the following fields are valid */
...@@ -669,37 +680,15 @@ static const struct attribute_group gl520_group_opt = { ...@@ -669,37 +680,15 @@ static const struct attribute_group gl520_group_opt = {
* Real code * Real code
*/ */
static int gl520_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
{ static int gl520_detect(struct i2c_client *client, int kind,
if (!(adapter->class & I2C_CLASS_HWMON)) struct i2c_board_info *info)
return 0;
return i2c_probe(adapter, &addr_data, gl520_detect);
}
static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
struct i2c_client *client; struct i2c_adapter *adapter = client->adapter;
struct gl520_data *data;
int err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA)) I2C_FUNC_SMBUS_WORD_DATA))
goto exit; return -ENODEV;
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access gl520_{read,write}_value. */
if (!(data = kzalloc(sizeof(struct gl520_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &gl520_driver;
/* Determine the chip type. */ /* Determine the chip type. */
if (kind < 0) { if (kind < 0) {
...@@ -707,24 +696,36 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -707,24 +696,36 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
((gl520_read_value(client, GL520_REG_REVISION) & 0x7f) != 0x00) || ((gl520_read_value(client, GL520_REG_REVISION) & 0x7f) != 0x00) ||
((gl520_read_value(client, GL520_REG_CONF) & 0x80) != 0x00)) { ((gl520_read_value(client, GL520_REG_CONF) & 0x80) != 0x00)) {
dev_dbg(&client->dev, "Unknown chip type, skipping\n"); dev_dbg(&client->dev, "Unknown chip type, skipping\n");
goto exit_free; return -ENODEV;
} }
} }
/* Fill in the remaining client fields */ strlcpy(info->type, "gl520sm", I2C_NAME_SIZE);
strlcpy(client->name, "gl520sm", I2C_NAME_SIZE);
mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ return 0;
if ((err = i2c_attach_client(client))) }
goto exit_free;
static int gl520_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct gl520_data *data;
int err;
data = kzalloc(sizeof(struct gl520_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
/* Initialize the GL520SM chip */ /* Initialize the GL520SM chip */
gl520_init_client(client); gl520_init_client(client);
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &gl520_group))) if ((err = sysfs_create_group(&client->dev.kobj, &gl520_group)))
goto exit_detach; goto exit_free;
if (data->two_temps) { if (data->two_temps) {
if ((err = device_create_file(&client->dev, if ((err = device_create_file(&client->dev,
...@@ -764,8 +765,6 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -764,8 +765,6 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove_files: exit_remove_files:
sysfs_remove_group(&client->dev.kobj, &gl520_group); sysfs_remove_group(&client->dev.kobj, &gl520_group);
sysfs_remove_group(&client->dev.kobj, &gl520_group_opt); sysfs_remove_group(&client->dev.kobj, &gl520_group_opt);
exit_detach:
i2c_detach_client(client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
...@@ -811,18 +810,14 @@ static void gl520_init_client(struct i2c_client *client) ...@@ -811,18 +810,14 @@ static void gl520_init_client(struct i2c_client *client)
gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask);
} }
static int gl520_detach_client(struct i2c_client *client) static int gl520_remove(struct i2c_client *client)
{ {
struct gl520_data *data = i2c_get_clientdata(client); struct gl520_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &gl520_group); sysfs_remove_group(&client->dev.kobj, &gl520_group);
sysfs_remove_group(&client->dev.kobj, &gl520_group_opt); sysfs_remove_group(&client->dev.kobj, &gl520_group_opt);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
} }
......
/* /*
* lm63.c - driver for the National Semiconductor LM63 temperature sensor * lm63.c - driver for the National Semiconductor LM63 temperature sensor
* with integrated fan control * with integrated fan control
* Copyright (C) 2004-2006 Jean Delvare <khali@linux-fr.org> * Copyright (C) 2004-2008 Jean Delvare <khali@linux-fr.org>
* Based on the lm90 driver. * Based on the lm90 driver.
* *
* The LM63 is a sensor chip made by National Semiconductor. It measures * The LM63 is a sensor chip made by National Semiconductor. It measures
...@@ -128,24 +128,36 @@ I2C_CLIENT_INSMOD_1(lm63); ...@@ -128,24 +128,36 @@ I2C_CLIENT_INSMOD_1(lm63);
* Functions declaration * Functions declaration
*/ */
static int lm63_attach_adapter(struct i2c_adapter *adapter); static int lm63_probe(struct i2c_client *client,
static int lm63_detach_client(struct i2c_client *client); const struct i2c_device_id *id);
static int lm63_remove(struct i2c_client *client);
static struct lm63_data *lm63_update_device(struct device *dev); static struct lm63_data *lm63_update_device(struct device *dev);
static int lm63_detect(struct i2c_adapter *adapter, int address, int kind); static int lm63_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static void lm63_init_client(struct i2c_client *client); static void lm63_init_client(struct i2c_client *client);
/* /*
* Driver data (common to all clients) * Driver data (common to all clients)
*/ */
static const struct i2c_device_id lm63_id[] = {
{ "lm63", lm63 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm63_id);
static struct i2c_driver lm63_driver = { static struct i2c_driver lm63_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "lm63", .name = "lm63",
}, },
.attach_adapter = lm63_attach_adapter, .probe = lm63_probe,
.detach_client = lm63_detach_client, .remove = lm63_remove,
.id_table = lm63_id,
.detect = lm63_detect,
.address_data = &addr_data,
}; };
/* /*
...@@ -153,7 +165,6 @@ static struct i2c_driver lm63_driver = { ...@@ -153,7 +165,6 @@ static struct i2c_driver lm63_driver = {
*/ */
struct lm63_data { struct lm63_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
...@@ -411,43 +422,14 @@ static const struct attribute_group lm63_group_fan1 = { ...@@ -411,43 +422,14 @@ static const struct attribute_group lm63_group_fan1 = {
* Real code * Real code
*/ */
static int lm63_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
static int lm63_detect(struct i2c_client *new_client, int kind,
struct i2c_board_info *info)
{ {
if (!(adapter->class & I2C_CLASS_HWMON)) struct i2c_adapter *adapter = new_client->adapter;
return 0;
return i2c_probe(adapter, &addr_data, lm63_detect);
}
/*
* The following function does more than just detection. If detection
* succeeds, it also registers the new chip.
*/
static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
struct lm63_data *data;
int err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit; return -ENODEV;
if (!(data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
/* The common I2C client data is placed right before the
LM63-specific data. */
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &lm63_driver;
new_client->flags = 0;
/* Default to an LM63 if forced */
if (kind == 0)
kind = lm63;
if (kind < 0) { /* must identify */ if (kind < 0) { /* must identify */
u8 man_id, chip_id, reg_config1, reg_config2; u8 man_id, chip_id, reg_config1, reg_config2;
...@@ -477,25 +459,38 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -477,25 +459,38 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
dev_dbg(&adapter->dev, "Unsupported chip " dev_dbg(&adapter->dev, "Unsupported chip "
"(man_id=0x%02X, chip_id=0x%02X).\n", "(man_id=0x%02X, chip_id=0x%02X).\n",
man_id, chip_id); man_id, chip_id);
goto exit_free; return -ENODEV;
} }
} }
strlcpy(new_client->name, "lm63", I2C_NAME_SIZE); strlcpy(info->type, "lm63", I2C_NAME_SIZE);
return 0;
}
static int lm63_probe(struct i2c_client *new_client,
const struct i2c_device_id *id)
{
struct lm63_data *data;
int err;
data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(new_client, data);
data->valid = 0; data->valid = 0;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_free;
/* Initialize the LM63 chip */ /* Initialize the LM63 chip */
lm63_init_client(new_client); lm63_init_client(new_client);
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, if ((err = sysfs_create_group(&new_client->dev.kobj,
&lm63_group))) &lm63_group)))
goto exit_detach; goto exit_free;
if (data->config & 0x04) { /* tachometer enabled */ if (data->config & 0x04) { /* tachometer enabled */
if ((err = sysfs_create_group(&new_client->dev.kobj, if ((err = sysfs_create_group(&new_client->dev.kobj,
&lm63_group_fan1))) &lm63_group_fan1)))
...@@ -513,8 +508,6 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -513,8 +508,6 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove_files: exit_remove_files:
sysfs_remove_group(&new_client->dev.kobj, &lm63_group); sysfs_remove_group(&new_client->dev.kobj, &lm63_group);
sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1); sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1);
exit_detach:
i2c_detach_client(new_client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
...@@ -556,18 +549,14 @@ static void lm63_init_client(struct i2c_client *client) ...@@ -556,18 +549,14 @@ static void lm63_init_client(struct i2c_client *client)
(data->config_fan & 0x20) ? "manual" : "auto"); (data->config_fan & 0x20) ? "manual" : "auto");
} }
static int lm63_detach_client(struct i2c_client *client) static int lm63_remove(struct i2c_client *client)
{ {
struct lm63_data *data = i2c_get_clientdata(client); struct lm63_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm63_group); sysfs_remove_group(&client->dev.kobj, &lm63_group);
sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1); sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -52,7 +52,6 @@ I2C_CLIENT_INSMOD_1(lm77); ...@@ -52,7 +52,6 @@ I2C_CLIENT_INSMOD_1(lm77);
/* Each client has this additional data */ /* Each client has this additional data */
struct lm77_data { struct lm77_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
char valid; char valid;
...@@ -65,23 +64,35 @@ struct lm77_data { ...@@ -65,23 +64,35 @@ struct lm77_data {
u8 alarms; u8 alarms;
}; };
static int lm77_attach_adapter(struct i2c_adapter *adapter); static int lm77_probe(struct i2c_client *client,
static int lm77_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int lm77_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static void lm77_init_client(struct i2c_client *client); static void lm77_init_client(struct i2c_client *client);
static int lm77_detach_client(struct i2c_client *client); static int lm77_remove(struct i2c_client *client);
static u16 lm77_read_value(struct i2c_client *client, u8 reg); static u16 lm77_read_value(struct i2c_client *client, u8 reg);
static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value); static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value);
static struct lm77_data *lm77_update_device(struct device *dev); static struct lm77_data *lm77_update_device(struct device *dev);
static const struct i2c_device_id lm77_id[] = {
{ "lm77", lm77 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm77_id);
/* This is the driver that will be inserted */ /* This is the driver that will be inserted */
static struct i2c_driver lm77_driver = { static struct i2c_driver lm77_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "lm77", .name = "lm77",
}, },
.attach_adapter = lm77_attach_adapter, .probe = lm77_probe,
.detach_client = lm77_detach_client, .remove = lm77_remove,
.id_table = lm77_id,
.detect = lm77_detect,
.address_data = &addr_data,
}; };
/* straight from the datasheet */ /* straight from the datasheet */
...@@ -215,13 +226,6 @@ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2); ...@@ -215,13 +226,6 @@ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2);
static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1); static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1);
static int lm77_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, lm77_detect);
}
static struct attribute *lm77_attributes[] = { static struct attribute *lm77_attributes[] = {
&dev_attr_temp1_input.attr, &dev_attr_temp1_input.attr,
&dev_attr_temp1_crit.attr, &dev_attr_temp1_crit.attr,
...@@ -240,32 +244,15 @@ static const struct attribute_group lm77_group = { ...@@ -240,32 +244,15 @@ static const struct attribute_group lm77_group = {
.attrs = lm77_attributes, .attrs = lm77_attributes,
}; };
/* This function is called by i2c_probe */ /* Return 0 if detection is successful, -ENODEV otherwise */
static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) static int lm77_detect(struct i2c_client *new_client, int kind,
struct i2c_board_info *info)
{ {
struct i2c_client *new_client; struct i2c_adapter *adapter = new_client->adapter;
struct lm77_data *data;
int err = 0;
const char *name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA)) I2C_FUNC_SMBUS_WORD_DATA))
goto exit; return -ENODEV;
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access lm77_{read,write}_value. */
if (!(data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &lm77_driver;
new_client->flags = 0;
/* Here comes the remaining detection. Since the LM77 has no /* Here comes the remaining detection. Since the LM77 has no
register dedicated to identification, we have to rely on the register dedicated to identification, we have to rely on the
...@@ -294,7 +281,7 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -294,7 +281,7 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
|| i2c_smbus_read_word_data(new_client, i + 3) != crit || i2c_smbus_read_word_data(new_client, i + 3) != crit
|| i2c_smbus_read_word_data(new_client, i + 4) != min || i2c_smbus_read_word_data(new_client, i + 4) != min
|| i2c_smbus_read_word_data(new_client, i + 5) != max) || i2c_smbus_read_word_data(new_client, i + 5) != max)
goto exit_free; return -ENODEV;
/* sign bits */ /* sign bits */
if (((cur & 0x00f0) != 0xf0 && (cur & 0x00f0) != 0x0) if (((cur & 0x00f0) != 0xf0 && (cur & 0x00f0) != 0x0)
...@@ -302,51 +289,55 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -302,51 +289,55 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
|| ((crit & 0x00f0) != 0xf0 && (crit & 0x00f0) != 0x0) || ((crit & 0x00f0) != 0xf0 && (crit & 0x00f0) != 0x0)
|| ((min & 0x00f0) != 0xf0 && (min & 0x00f0) != 0x0) || ((min & 0x00f0) != 0xf0 && (min & 0x00f0) != 0x0)
|| ((max & 0x00f0) != 0xf0 && (max & 0x00f0) != 0x0)) || ((max & 0x00f0) != 0xf0 && (max & 0x00f0) != 0x0))
goto exit_free; return -ENODEV;
/* unused bits */ /* unused bits */
if (conf & 0xe0) if (conf & 0xe0)
goto exit_free; return -ENODEV;
/* 0x06 and 0x07 return the last read value */ /* 0x06 and 0x07 return the last read value */
cur = i2c_smbus_read_word_data(new_client, 0); cur = i2c_smbus_read_word_data(new_client, 0);
if (i2c_smbus_read_word_data(new_client, 6) != cur if (i2c_smbus_read_word_data(new_client, 6) != cur
|| i2c_smbus_read_word_data(new_client, 7) != cur) || i2c_smbus_read_word_data(new_client, 7) != cur)
goto exit_free; return -ENODEV;
hyst = i2c_smbus_read_word_data(new_client, 2); hyst = i2c_smbus_read_word_data(new_client, 2);
if (i2c_smbus_read_word_data(new_client, 6) != hyst if (i2c_smbus_read_word_data(new_client, 6) != hyst
|| i2c_smbus_read_word_data(new_client, 7) != hyst) || i2c_smbus_read_word_data(new_client, 7) != hyst)
goto exit_free; return -ENODEV;
min = i2c_smbus_read_word_data(new_client, 4); min = i2c_smbus_read_word_data(new_client, 4);
if (i2c_smbus_read_word_data(new_client, 6) != min if (i2c_smbus_read_word_data(new_client, 6) != min
|| i2c_smbus_read_word_data(new_client, 7) != min) || i2c_smbus_read_word_data(new_client, 7) != min)
goto exit_free; return -ENODEV;
} }
/* Determine the chip type - only one kind supported! */ strlcpy(info->type, "lm77", I2C_NAME_SIZE);
if (kind <= 0)
kind = lm77;
if (kind == lm77) { return 0;
name = "lm77"; }
static int lm77_probe(struct i2c_client *new_client,
const struct i2c_device_id *id)
{
struct lm77_data *data;
int err;
data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
} }
/* Fill in the remaining client fields and put it into the global list */ i2c_set_clientdata(new_client, data);
strlcpy(new_client->name, name, I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_free;
/* Initialize the LM77 chip */ /* Initialize the LM77 chip */
lm77_init_client(new_client); lm77_init_client(new_client);
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group))) if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group)))
goto exit_detach; goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev); data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -358,20 +349,17 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -358,20 +349,17 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove: exit_remove:
sysfs_remove_group(&new_client->dev.kobj, &lm77_group); sysfs_remove_group(&new_client->dev.kobj, &lm77_group);
exit_detach:
i2c_detach_client(new_client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int lm77_detach_client(struct i2c_client *client) static int lm77_remove(struct i2c_client *client)
{ {
struct lm77_data *data = i2c_get_clientdata(client); struct lm77_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm77_group); sysfs_remove_group(&client->dev.kobj, &lm77_group);
i2c_detach_client(client);
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -108,7 +108,6 @@ static inline long TEMP_FROM_REG(u16 temp) ...@@ -108,7 +108,6 @@ static inline long TEMP_FROM_REG(u16 temp)
*/ */
struct lm80_data { struct lm80_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
...@@ -132,10 +131,12 @@ struct lm80_data { ...@@ -132,10 +131,12 @@ struct lm80_data {
* Functions declaration * Functions declaration
*/ */
static int lm80_attach_adapter(struct i2c_adapter *adapter); static int lm80_probe(struct i2c_client *client,
static int lm80_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int lm80_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static void lm80_init_client(struct i2c_client *client); static void lm80_init_client(struct i2c_client *client);
static int lm80_detach_client(struct i2c_client *client); static int lm80_remove(struct i2c_client *client);
static struct lm80_data *lm80_update_device(struct device *dev); static struct lm80_data *lm80_update_device(struct device *dev);
static int lm80_read_value(struct i2c_client *client, u8 reg); static int lm80_read_value(struct i2c_client *client, u8 reg);
static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value); static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
...@@ -144,12 +145,22 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value); ...@@ -144,12 +145,22 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
* Driver data (common to all clients) * Driver data (common to all clients)
*/ */
static const struct i2c_device_id lm80_id[] = {
{ "lm80", lm80 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm80_id);
static struct i2c_driver lm80_driver = { static struct i2c_driver lm80_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "lm80", .name = "lm80",
}, },
.attach_adapter = lm80_attach_adapter, .probe = lm80_probe,
.detach_client = lm80_detach_client, .remove = lm80_remove,
.id_table = lm80_id,
.detect = lm80_detect,
.address_data = &addr_data,
}; };
/* /*
...@@ -383,13 +394,6 @@ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 13); ...@@ -383,13 +394,6 @@ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 13);
* Real code * Real code
*/ */
static int lm80_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, lm80_detect);
}
static struct attribute *lm80_attributes[] = { static struct attribute *lm80_attributes[] = {
&sensor_dev_attr_in0_min.dev_attr.attr, &sensor_dev_attr_in0_min.dev_attr.attr,
&sensor_dev_attr_in1_min.dev_attr.attr, &sensor_dev_attr_in1_min.dev_attr.attr,
...@@ -442,53 +446,46 @@ static const struct attribute_group lm80_group = { ...@@ -442,53 +446,46 @@ static const struct attribute_group lm80_group = {
.attrs = lm80_attributes, .attrs = lm80_attributes,
}; };
static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) /* Return 0 if detection is successful, -ENODEV otherwise */
static int lm80_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter;
int i, cur; int i, cur;
struct i2c_client *client;
struct lm80_data *data;
int err = 0;
const char *name;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit; return -ENODEV;
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access lm80_{read,write}_value. */
if (!(data = kzalloc(sizeof(struct lm80_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &lm80_driver;
/* Now, we do the remaining detection. It is lousy. */ /* Now, we do the remaining detection. It is lousy. */
if (lm80_read_value(client, LM80_REG_ALARM2) & 0xc0) if (lm80_read_value(client, LM80_REG_ALARM2) & 0xc0)
goto error_free; return -ENODEV;
for (i = 0x2a; i <= 0x3d; i++) { for (i = 0x2a; i <= 0x3d; i++) {
cur = i2c_smbus_read_byte_data(client, i); cur = i2c_smbus_read_byte_data(client, i);
if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur) if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur)
|| (i2c_smbus_read_byte_data(client, i + 0x80) != cur) || (i2c_smbus_read_byte_data(client, i + 0x80) != cur)
|| (i2c_smbus_read_byte_data(client, i + 0xc0) != cur)) || (i2c_smbus_read_byte_data(client, i + 0xc0) != cur))
goto error_free; return -ENODEV;
} }
/* Determine the chip type - only one kind supported! */ strlcpy(info->type, "lm80", I2C_NAME_SIZE);
kind = lm80;
name = "lm80";
/* Fill in the remaining client fields */ return 0;
strlcpy(client->name, name, I2C_NAME_SIZE); }
mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ static int lm80_probe(struct i2c_client *client,
if ((err = i2c_attach_client(client))) const struct i2c_device_id *id)
goto error_free; {
struct lm80_data *data;
int err;
data = kzalloc(sizeof(struct lm80_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
/* Initialize the LM80 chip */ /* Initialize the LM80 chip */
lm80_init_client(client); lm80_init_client(client);
...@@ -499,7 +496,7 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -499,7 +496,7 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &lm80_group))) if ((err = sysfs_create_group(&client->dev.kobj, &lm80_group)))
goto error_detach; goto error_free;
data->hwmon_dev = hwmon_device_register(&client->dev); data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -511,23 +508,18 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -511,23 +508,18 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
error_remove: error_remove:
sysfs_remove_group(&client->dev.kobj, &lm80_group); sysfs_remove_group(&client->dev.kobj, &lm80_group);
error_detach:
i2c_detach_client(client);
error_free: error_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int lm80_detach_client(struct i2c_client *client) static int lm80_remove(struct i2c_client *client)
{ {
struct lm80_data *data = i2c_get_clientdata(client); struct lm80_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm80_group); sysfs_remove_group(&client->dev.kobj, &lm80_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
......
/* /*
* lm83.c - Part of lm_sensors, Linux kernel modules for hardware * lm83.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring * monitoring
* Copyright (C) 2003-2006 Jean Delvare <khali@linux-fr.org> * Copyright (C) 2003-2008 Jean Delvare <khali@linux-fr.org>
* *
* Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is * Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is
* a sensor chip made by National Semiconductor. It reports up to four * a sensor chip made by National Semiconductor. It reports up to four
...@@ -118,21 +118,34 @@ static const u8 LM83_REG_W_HIGH[] = { ...@@ -118,21 +118,34 @@ static const u8 LM83_REG_W_HIGH[] = {
* Functions declaration * Functions declaration
*/ */
static int lm83_attach_adapter(struct i2c_adapter *adapter); static int lm83_detect(struct i2c_client *new_client, int kind,
static int lm83_detect(struct i2c_adapter *adapter, int address, int kind); struct i2c_board_info *info);
static int lm83_detach_client(struct i2c_client *client); static int lm83_probe(struct i2c_client *client,
const struct i2c_device_id *id);
static int lm83_remove(struct i2c_client *client);
static struct lm83_data *lm83_update_device(struct device *dev); static struct lm83_data *lm83_update_device(struct device *dev);
/* /*
* Driver data (common to all clients) * Driver data (common to all clients)
*/ */
static const struct i2c_device_id lm83_id[] = {
{ "lm83", lm83 },
{ "lm82", lm82 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm83_id);
static struct i2c_driver lm83_driver = { static struct i2c_driver lm83_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "lm83", .name = "lm83",
}, },
.attach_adapter = lm83_attach_adapter, .probe = lm83_probe,
.detach_client = lm83_detach_client, .remove = lm83_remove,
.id_table = lm83_id,
.detect = lm83_detect,
.address_data = &addr_data,
}; };
/* /*
...@@ -140,7 +153,6 @@ static struct i2c_driver lm83_driver = { ...@@ -140,7 +153,6 @@ static struct i2c_driver lm83_driver = {
*/ */
struct lm83_data { struct lm83_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
...@@ -278,40 +290,15 @@ static const struct attribute_group lm83_group_opt = { ...@@ -278,40 +290,15 @@ static const struct attribute_group lm83_group_opt = {
* Real code * Real code
*/ */
static int lm83_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
static int lm83_detect(struct i2c_client *new_client, int kind,
struct i2c_board_info *info)
{ {
if (!(adapter->class & I2C_CLASS_HWMON)) struct i2c_adapter *adapter = new_client->adapter;
return 0;
return i2c_probe(adapter, &addr_data, lm83_detect);
}
/*
* The following function does more than just detection. If detection
* succeeds, it also registers the new chip.
*/
static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
struct lm83_data *data;
int err = 0;
const char *name = ""; const char *name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit; return -ENODEV;
if (!(data = kzalloc(sizeof(struct lm83_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
/* The common I2C client data is placed right after the
* LM83-specific data. */
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &lm83_driver;
new_client->flags = 0;
/* Now we do the detection and identification. A negative kind /* Now we do the detection and identification. A negative kind
* means that the driver was loaded with no force parameter * means that the driver was loaded with no force parameter
...@@ -335,8 +322,9 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -335,8 +322,9 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
((i2c_smbus_read_byte_data(new_client, LM83_REG_R_CONFIG) ((i2c_smbus_read_byte_data(new_client, LM83_REG_R_CONFIG)
& 0x41) != 0x00)) { & 0x41) != 0x00)) {
dev_dbg(&adapter->dev, dev_dbg(&adapter->dev,
"LM83 detection failed at 0x%02x.\n", address); "LM83 detection failed at 0x%02x.\n",
goto exit_free; new_client->addr);
return -ENODEV;
} }
} }
...@@ -361,7 +349,7 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -361,7 +349,7 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&adapter->dev, dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, " "Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X).\n", man_id, chip_id); "chip_id=0x%02X).\n", man_id, chip_id);
goto exit_free; return -ENODEV;
} }
} }
...@@ -372,15 +360,27 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -372,15 +360,27 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
name = "lm82"; name = "lm82";
} }
/* We can fill in the remaining client fields */ strlcpy(info->type, name, I2C_NAME_SIZE);
strlcpy(new_client->name, name, I2C_NAME_SIZE);
return 0;
}
static int lm83_probe(struct i2c_client *new_client,
const struct i2c_device_id *id)
{
struct lm83_data *data;
int err;
data = kzalloc(sizeof(struct lm83_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(new_client, data);
data->valid = 0; data->valid = 0;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_free;
/* /*
* Register sysfs hooks * Register sysfs hooks
* The LM82 can only monitor one external diode which is * The LM82 can only monitor one external diode which is
...@@ -389,9 +389,9 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -389,9 +389,9 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
*/ */
if ((err = sysfs_create_group(&new_client->dev.kobj, &lm83_group))) if ((err = sysfs_create_group(&new_client->dev.kobj, &lm83_group)))
goto exit_detach; goto exit_free;
if (kind == lm83) { if (id->driver_data == lm83) {
if ((err = sysfs_create_group(&new_client->dev.kobj, if ((err = sysfs_create_group(&new_client->dev.kobj,
&lm83_group_opt))) &lm83_group_opt)))
goto exit_remove_files; goto exit_remove_files;
...@@ -408,26 +408,20 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -408,26 +408,20 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove_files: exit_remove_files:
sysfs_remove_group(&new_client->dev.kobj, &lm83_group); sysfs_remove_group(&new_client->dev.kobj, &lm83_group);
sysfs_remove_group(&new_client->dev.kobj, &lm83_group_opt); sysfs_remove_group(&new_client->dev.kobj, &lm83_group_opt);
exit_detach:
i2c_detach_client(new_client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int lm83_detach_client(struct i2c_client *client) static int lm83_remove(struct i2c_client *client)
{ {
struct lm83_data *data = i2c_get_clientdata(client); struct lm83_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm83_group); sysfs_remove_group(&client->dev.kobj, &lm83_group);
sysfs_remove_group(&client->dev.kobj, &lm83_group_opt); sysfs_remove_group(&client->dev.kobj, &lm83_group_opt);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Philip Edelbrock <phil@netroedge.com> * Philip Edelbrock <phil@netroedge.com>
* Stephen Rousset <stephen.rousset@rocketlogix.com> * Stephen Rousset <stephen.rousset@rocketlogix.com>
* Dan Eaton <dan.eaton@rocketlogix.com> * Dan Eaton <dan.eaton@rocketlogix.com>
* Copyright (C) 2004,2007 Jean Delvare <khali@linux-fr.org> * Copyright (C) 2004-2008 Jean Delvare <khali@linux-fr.org>
* *
* Original port to Linux 2.6 by Jeff Oliver. * Original port to Linux 2.6 by Jeff Oliver.
* *
...@@ -157,22 +157,35 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A, 0x38, 0x2C }; ...@@ -157,22 +157,35 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A, 0x38, 0x2C };
* Functions declaration * Functions declaration
*/ */
static int lm87_attach_adapter(struct i2c_adapter *adapter); static int lm87_probe(struct i2c_client *client,
static int lm87_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int lm87_detect(struct i2c_client *new_client, int kind,
struct i2c_board_info *info);
static void lm87_init_client(struct i2c_client *client); static void lm87_init_client(struct i2c_client *client);
static int lm87_detach_client(struct i2c_client *client); static int lm87_remove(struct i2c_client *client);
static struct lm87_data *lm87_update_device(struct device *dev); static struct lm87_data *lm87_update_device(struct device *dev);
/* /*
* Driver data (common to all clients) * Driver data (common to all clients)
*/ */
static const struct i2c_device_id lm87_id[] = {
{ "lm87", lm87 },
{ "adm1024", adm1024 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm87_id);
static struct i2c_driver lm87_driver = { static struct i2c_driver lm87_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "lm87", .name = "lm87",
}, },
.attach_adapter = lm87_attach_adapter, .probe = lm87_probe,
.detach_client = lm87_detach_client, .remove = lm87_remove,
.id_table = lm87_id,
.detect = lm87_detect,
.address_data = &addr_data,
}; };
/* /*
...@@ -180,7 +193,6 @@ static struct i2c_driver lm87_driver = { ...@@ -180,7 +193,6 @@ static struct i2c_driver lm87_driver = {
*/ */
struct lm87_data { struct lm87_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
...@@ -562,13 +574,6 @@ static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 15); ...@@ -562,13 +574,6 @@ static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 15);
* Real code * Real code
*/ */
static int lm87_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, lm87_detect);
}
static struct attribute *lm87_attributes[] = { static struct attribute *lm87_attributes[] = {
&dev_attr_in1_input.attr, &dev_attr_in1_input.attr,
&dev_attr_in1_min.attr, &dev_attr_in1_min.attr,
...@@ -656,33 +661,15 @@ static const struct attribute_group lm87_group_opt = { ...@@ -656,33 +661,15 @@ static const struct attribute_group lm87_group_opt = {
.attrs = lm87_attributes_opt, .attrs = lm87_attributes_opt,
}; };
/* /* Return 0 if detection is successful, -ENODEV otherwise */
* The following function does more than just detection. If detection static int lm87_detect(struct i2c_client *new_client, int kind,
* succeeds, it also registers the new chip. struct i2c_board_info *info)
*/
static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
struct i2c_client *new_client; struct i2c_adapter *adapter = new_client->adapter;
struct lm87_data *data;
int err = 0;
static const char *names[] = { "lm87", "adm1024" }; static const char *names[] = { "lm87", "adm1024" };
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit; return -ENODEV;
if (!(data = kzalloc(sizeof(struct lm87_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
/* The common I2C client data is placed right before the
LM87-specific data. */
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &lm87_driver;
new_client->flags = 0;
/* Default to an LM87 if forced */ /* Default to an LM87 if forced */
if (kind == 0) if (kind == 0)
...@@ -704,20 +691,32 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -704,20 +691,32 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
|| (lm87_read_value(new_client, LM87_REG_CONFIG) & 0x80)) { || (lm87_read_value(new_client, LM87_REG_CONFIG) & 0x80)) {
dev_dbg(&adapter->dev, dev_dbg(&adapter->dev,
"LM87 detection failed at 0x%02x.\n", "LM87 detection failed at 0x%02x.\n",
address); new_client->addr);
goto exit_free; return -ENODEV;
} }
} }
/* We can fill in the remaining client fields */ strlcpy(info->type, names[kind - 1], I2C_NAME_SIZE);
strlcpy(new_client->name, names[kind - 1], I2C_NAME_SIZE);
return 0;
}
static int lm87_probe(struct i2c_client *new_client,
const struct i2c_device_id *id)
{
struct lm87_data *data;
int err;
data = kzalloc(sizeof(struct lm87_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(new_client, data);
data->valid = 0; data->valid = 0;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_free;
/* Initialize the LM87 chip */ /* Initialize the LM87 chip */
lm87_init_client(new_client); lm87_init_client(new_client);
...@@ -732,7 +731,7 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -732,7 +731,7 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &lm87_group))) if ((err = sysfs_create_group(&new_client->dev.kobj, &lm87_group)))
goto exit_detach; goto exit_free;
if (data->channel & CHAN_NO_FAN(0)) { if (data->channel & CHAN_NO_FAN(0)) {
if ((err = device_create_file(&new_client->dev, if ((err = device_create_file(&new_client->dev,
...@@ -832,8 +831,6 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -832,8 +831,6 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove: exit_remove:
sysfs_remove_group(&new_client->dev.kobj, &lm87_group); sysfs_remove_group(&new_client->dev.kobj, &lm87_group);
sysfs_remove_group(&new_client->dev.kobj, &lm87_group_opt); sysfs_remove_group(&new_client->dev.kobj, &lm87_group_opt);
exit_detach:
i2c_detach_client(new_client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
...@@ -877,18 +874,14 @@ static void lm87_init_client(struct i2c_client *client) ...@@ -877,18 +874,14 @@ static void lm87_init_client(struct i2c_client *client)
} }
} }
static int lm87_detach_client(struct i2c_client *client) static int lm87_remove(struct i2c_client *client)
{ {
struct lm87_data *data = i2c_get_clientdata(client); struct lm87_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm87_group); sysfs_remove_group(&client->dev.kobj, &lm87_group);
sysfs_remove_group(&client->dev.kobj, &lm87_group_opt); sysfs_remove_group(&client->dev.kobj, &lm87_group_opt);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
} }
......
...@@ -187,23 +187,44 @@ I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680); ...@@ -187,23 +187,44 @@ I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680);
* Functions declaration * Functions declaration
*/ */
static int lm90_attach_adapter(struct i2c_adapter *adapter); static int lm90_detect(struct i2c_client *client, int kind,
static int lm90_detect(struct i2c_adapter *adapter, int address, struct i2c_board_info *info);
int kind); static int lm90_probe(struct i2c_client *client,
const struct i2c_device_id *id);
static void lm90_init_client(struct i2c_client *client); static void lm90_init_client(struct i2c_client *client);
static int lm90_detach_client(struct i2c_client *client); static int lm90_remove(struct i2c_client *client);
static struct lm90_data *lm90_update_device(struct device *dev); static struct lm90_data *lm90_update_device(struct device *dev);
/* /*
* Driver data (common to all clients) * Driver data (common to all clients)
*/ */
static const struct i2c_device_id lm90_id[] = {
{ "adm1032", adm1032 },
{ "adt7461", adt7461 },
{ "lm90", lm90 },
{ "lm86", lm86 },
{ "lm89", lm99 },
{ "lm99", lm99 }, /* Missing temperature offset */
{ "max6657", max6657 },
{ "max6658", max6657 },
{ "max6659", max6657 },
{ "max6680", max6680 },
{ "max6681", max6680 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm90_id);
static struct i2c_driver lm90_driver = { static struct i2c_driver lm90_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "lm90", .name = "lm90",
}, },
.attach_adapter = lm90_attach_adapter, .probe = lm90_probe,
.detach_client = lm90_detach_client, .remove = lm90_remove,
.id_table = lm90_id,
.detect = lm90_detect,
.address_data = &addr_data,
}; };
/* /*
...@@ -211,7 +232,6 @@ static struct i2c_driver lm90_driver = { ...@@ -211,7 +232,6 @@ static struct i2c_driver lm90_driver = {
*/ */
struct lm90_data { struct lm90_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
...@@ -477,40 +497,16 @@ static int lm90_read_reg(struct i2c_client* client, u8 reg, u8 *value) ...@@ -477,40 +497,16 @@ static int lm90_read_reg(struct i2c_client* client, u8 reg, u8 *value)
return 0; return 0;
} }
static int lm90_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
{ static int lm90_detect(struct i2c_client *new_client, int kind,
if (!(adapter->class & I2C_CLASS_HWMON)) struct i2c_board_info *info)
return 0;
return i2c_probe(adapter, &addr_data, lm90_detect);
}
/*
* The following function does more than just detection. If detection
* succeeds, it also registers the new chip.
*/
static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
struct i2c_client *new_client; struct i2c_adapter *adapter = new_client->adapter;
struct lm90_data *data; int address = new_client->addr;
int err = 0;
const char *name = ""; const char *name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit; return -ENODEV;
if (!(data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
/* The common I2C client data is placed right before the
LM90-specific data. */
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &lm90_driver;
new_client->flags = 0;
/* /*
* Now we do the remaining detection. A negative kind means that * Now we do the remaining detection. A negative kind means that
...@@ -538,7 +534,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -538,7 +534,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
LM90_REG_R_CONFIG1)) < 0 LM90_REG_R_CONFIG1)) < 0
|| (reg_convrate = i2c_smbus_read_byte_data(new_client, || (reg_convrate = i2c_smbus_read_byte_data(new_client,
LM90_REG_R_CONVRATE)) < 0) LM90_REG_R_CONVRATE)) < 0)
goto exit_free; return -ENODEV;
if ((address == 0x4C || address == 0x4D) if ((address == 0x4C || address == 0x4D)
&& man_id == 0x01) { /* National Semiconductor */ && man_id == 0x01) { /* National Semiconductor */
...@@ -546,7 +542,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -546,7 +542,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
if ((reg_config2 = i2c_smbus_read_byte_data(new_client, if ((reg_config2 = i2c_smbus_read_byte_data(new_client,
LM90_REG_R_CONFIG2)) < 0) LM90_REG_R_CONFIG2)) < 0)
goto exit_free; return -ENODEV;
if ((reg_config1 & 0x2A) == 0x00 if ((reg_config1 & 0x2A) == 0x00
&& (reg_config2 & 0xF8) == 0x00 && (reg_config2 & 0xF8) == 0x00
...@@ -610,10 +606,11 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -610,10 +606,11 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&adapter->dev, dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, " "Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X).\n", man_id, chip_id); "chip_id=0x%02X).\n", man_id, chip_id);
goto exit_free; return -ENODEV;
} }
} }
/* Fill the i2c board info */
if (kind == lm90) { if (kind == lm90) {
name = "lm90"; name = "lm90";
} else if (kind == adm1032) { } else if (kind == adm1032) {
...@@ -621,7 +618,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -621,7 +618,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
/* The ADM1032 supports PEC, but only if combined /* The ADM1032 supports PEC, but only if combined
transactions are not used. */ transactions are not used. */
if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
new_client->flags |= I2C_CLIENT_PEC; info->flags |= I2C_CLIENT_PEC;
} else if (kind == lm99) { } else if (kind == lm99) {
name = "lm99"; name = "lm99";
} else if (kind == lm86) { } else if (kind == lm86) {
...@@ -633,23 +630,39 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -633,23 +630,39 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
} else if (kind == adt7461) { } else if (kind == adt7461) {
name = "adt7461"; name = "adt7461";
} }
strlcpy(info->type, name, I2C_NAME_SIZE);
return 0;
}
static int lm90_probe(struct i2c_client *new_client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = to_i2c_adapter(new_client->dev.parent);
struct lm90_data *data;
int err;
/* We can fill in the remaining client fields */ data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL);
strlcpy(new_client->name, name, I2C_NAME_SIZE); if (!data) {
data->valid = 0; err = -ENOMEM;
data->kind = kind; goto exit;
}
i2c_set_clientdata(new_client, data);
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Set the device type */
if ((err = i2c_attach_client(new_client))) data->kind = id->driver_data;
goto exit_free; if (data->kind == adm1032) {
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
new_client->flags &= ~I2C_CLIENT_PEC;
}
/* Initialize the LM90 chip */ /* Initialize the LM90 chip */
lm90_init_client(new_client); lm90_init_client(new_client);
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &lm90_group))) if ((err = sysfs_create_group(&new_client->dev.kobj, &lm90_group)))
goto exit_detach; goto exit_free;
if (new_client->flags & I2C_CLIENT_PEC) { if (new_client->flags & I2C_CLIENT_PEC) {
if ((err = device_create_file(&new_client->dev, if ((err = device_create_file(&new_client->dev,
&dev_attr_pec))) &dev_attr_pec)))
...@@ -672,8 +685,6 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -672,8 +685,6 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove_files: exit_remove_files:
sysfs_remove_group(&new_client->dev.kobj, &lm90_group); sysfs_remove_group(&new_client->dev.kobj, &lm90_group);
device_remove_file(&new_client->dev, &dev_attr_pec); device_remove_file(&new_client->dev, &dev_attr_pec);
exit_detach:
i2c_detach_client(new_client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
...@@ -710,10 +721,9 @@ static void lm90_init_client(struct i2c_client *client) ...@@ -710,10 +721,9 @@ static void lm90_init_client(struct i2c_client *client)
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config);
} }
static int lm90_detach_client(struct i2c_client *client) static int lm90_remove(struct i2c_client *client)
{ {
struct lm90_data *data = i2c_get_clientdata(client); struct lm90_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm90_group); sysfs_remove_group(&client->dev.kobj, &lm90_group);
...@@ -722,9 +732,6 @@ static int lm90_detach_client(struct i2c_client *client) ...@@ -722,9 +732,6 @@ static int lm90_detach_client(struct i2c_client *client)
device_remove_file(&client->dev, device_remove_file(&client->dev,
&sensor_dev_attr_temp2_offset.dev_attr); &sensor_dev_attr_temp2_offset.dev_attr);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
} }
......
/* /*
* lm92 - Hardware monitoring driver * lm92 - Hardware monitoring driver
* Copyright (C) 2005 Jean Delvare <khali@linux-fr.org> * Copyright (C) 2005-2008 Jean Delvare <khali@linux-fr.org>
* *
* Based on the lm90 driver, with some ideas taken from the lm_sensors * Based on the lm90 driver, with some ideas taken from the lm_sensors
* lm92 driver as well. * lm92 driver as well.
...@@ -96,7 +96,6 @@ static struct i2c_driver lm92_driver; ...@@ -96,7 +96,6 @@ static struct i2c_driver lm92_driver;
/* Client data (each client gets its own) */ /* Client data (each client gets its own) */
struct lm92_data { struct lm92_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
...@@ -319,32 +318,15 @@ static const struct attribute_group lm92_group = { ...@@ -319,32 +318,15 @@ static const struct attribute_group lm92_group = {
.attrs = lm92_attributes, .attrs = lm92_attributes,
}; };
/* The following function does more than just detection. If detection /* Return 0 if detection is successful, -ENODEV otherwise */
succeeds, it also registers the new chip. */ static int lm92_detect(struct i2c_client *new_client, int kind,
static int lm92_detect(struct i2c_adapter *adapter, int address, int kind) struct i2c_board_info *info)
{ {
struct i2c_client *new_client; struct i2c_adapter *adapter = new_client->adapter;
struct lm92_data *data;
int err = 0;
char *name;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_WORD_DATA)) | I2C_FUNC_SMBUS_WORD_DATA))
goto exit; return -ENODEV;
if (!(data = kzalloc(sizeof(struct lm92_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
/* Fill in enough client fields so that we can read from the chip,
which is required for identication */
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &lm92_driver;
new_client->flags = 0;
/* A negative kind means that the driver was loaded with no force /* A negative kind means that the driver was loaded with no force
parameter (default), so we must identify the chip. */ parameter (default), so we must identify the chip. */
...@@ -364,34 +346,36 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -364,34 +346,36 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
kind = lm92; /* No separate prefix */ kind = lm92; /* No separate prefix */
} }
else else
goto exit_free; return -ENODEV;
} else
if (kind == 0) /* Default to an LM92 if forced */
kind = lm92;
/* Give it the proper name */
if (kind == lm92) {
name = "lm92";
} else { /* Supposedly cannot happen */
dev_dbg(&new_client->dev, "Kind out of range?\n");
goto exit_free;
} }
/* Fill in the remaining client fields */ strlcpy(info->type, "lm92", I2C_NAME_SIZE);
strlcpy(new_client->name, name, I2C_NAME_SIZE);
return 0;
}
static int lm92_probe(struct i2c_client *new_client,
const struct i2c_device_id *id)
{
struct lm92_data *data;
int err;
data = kzalloc(sizeof(struct lm92_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(new_client, data);
data->valid = 0; data->valid = 0;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the i2c subsystem a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_free;
/* Initialize the chipset */ /* Initialize the chipset */
lm92_init_client(new_client); lm92_init_client(new_client);
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &lm92_group))) if ((err = sysfs_create_group(&new_client->dev.kobj, &lm92_group)))
goto exit_detach; goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev); data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -403,32 +387,19 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -403,32 +387,19 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove: exit_remove:
sysfs_remove_group(&new_client->dev.kobj, &lm92_group); sysfs_remove_group(&new_client->dev.kobj, &lm92_group);
exit_detach:
i2c_detach_client(new_client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int lm92_attach_adapter(struct i2c_adapter *adapter) static int lm92_remove(struct i2c_client *client)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, lm92_detect);
}
static int lm92_detach_client(struct i2c_client *client)
{ {
struct lm92_data *data = i2c_get_clientdata(client); struct lm92_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm92_group); sysfs_remove_group(&client->dev.kobj, &lm92_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
} }
...@@ -438,12 +409,23 @@ static int lm92_detach_client(struct i2c_client *client) ...@@ -438,12 +409,23 @@ static int lm92_detach_client(struct i2c_client *client)
* Module and driver stuff * Module and driver stuff
*/ */
static const struct i2c_device_id lm92_id[] = {
{ "lm92", lm92 },
/* max6635 could be added here */
{ }
};
MODULE_DEVICE_TABLE(i2c, lm92_id);
static struct i2c_driver lm92_driver = { static struct i2c_driver lm92_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "lm92", .name = "lm92",
}, },
.attach_adapter = lm92_attach_adapter, .probe = lm92_probe,
.detach_client = lm92_detach_client, .remove = lm92_remove,
.id_table = lm92_id,
.detect = lm92_detect,
.address_data = &addr_data,
}; };
static int __init sensors_lm92_init(void) static int __init sensors_lm92_init(void)
......
This diff is collapsed.
...@@ -79,23 +79,34 @@ I2C_CLIENT_INSMOD_1(max1619); ...@@ -79,23 +79,34 @@ I2C_CLIENT_INSMOD_1(max1619);
* Functions declaration * Functions declaration
*/ */
static int max1619_attach_adapter(struct i2c_adapter *adapter); static int max1619_probe(struct i2c_client *client,
static int max1619_detect(struct i2c_adapter *adapter, int address, const struct i2c_device_id *id);
int kind); static int max1619_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static void max1619_init_client(struct i2c_client *client); static void max1619_init_client(struct i2c_client *client);
static int max1619_detach_client(struct i2c_client *client); static int max1619_remove(struct i2c_client *client);
static struct max1619_data *max1619_update_device(struct device *dev); static struct max1619_data *max1619_update_device(struct device *dev);
/* /*
* Driver data (common to all clients) * Driver data (common to all clients)
*/ */
static const struct i2c_device_id max1619_id[] = {
{ "max1619", max1619 },
{ }
};
MODULE_DEVICE_TABLE(i2c, max1619_id);
static struct i2c_driver max1619_driver = { static struct i2c_driver max1619_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "max1619", .name = "max1619",
}, },
.attach_adapter = max1619_attach_adapter, .probe = max1619_probe,
.detach_client = max1619_detach_client, .remove = max1619_remove,
.id_table = max1619_id,
.detect = max1619_detect,
.address_data = &addr_data,
}; };
/* /*
...@@ -103,7 +114,6 @@ static struct i2c_driver max1619_driver = { ...@@ -103,7 +114,6 @@ static struct i2c_driver max1619_driver = {
*/ */
struct max1619_data { struct max1619_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
...@@ -208,41 +218,15 @@ static const struct attribute_group max1619_group = { ...@@ -208,41 +218,15 @@ static const struct attribute_group max1619_group = {
* Real code * Real code
*/ */
static int max1619_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
{ static int max1619_detect(struct i2c_client *new_client, int kind,
if (!(adapter->class & I2C_CLASS_HWMON)) struct i2c_board_info *info)
return 0;
return i2c_probe(adapter, &addr_data, max1619_detect);
}
/*
* The following function does more than just detection. If detection
* succeeds, it also registers the new chip.
*/
static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
struct i2c_client *new_client; struct i2c_adapter *adapter = new_client->adapter;
struct max1619_data *data;
int err = 0;
const char *name = "";
u8 reg_config=0, reg_convrate=0, reg_status=0; u8 reg_config=0, reg_convrate=0, reg_status=0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit; return -ENODEV;
if (!(data = kzalloc(sizeof(struct max1619_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
/* The common I2C client data is placed right before the
MAX1619-specific data. */
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &max1619_driver;
new_client->flags = 0;
/* /*
* Now we do the remaining detection. A negative kind means that * Now we do the remaining detection. A negative kind means that
...@@ -265,8 +249,8 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -265,8 +249,8 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
|| reg_convrate > 0x07 || (reg_status & 0x61 ) !=0x00) { || reg_convrate > 0x07 || (reg_status & 0x61 ) !=0x00) {
dev_dbg(&adapter->dev, dev_dbg(&adapter->dev,
"MAX1619 detection failed at 0x%02x.\n", "MAX1619 detection failed at 0x%02x.\n",
address); new_client->addr);
goto exit_free; return -ENODEV;
} }
} }
...@@ -285,28 +269,37 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -285,28 +269,37 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&adapter->dev, dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, " "Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X).\n", man_id, chip_id); "chip_id=0x%02X).\n", man_id, chip_id);
goto exit_free; return -ENODEV;
} }
} }
if (kind == max1619) strlcpy(info->type, "max1619", I2C_NAME_SIZE);
name = "max1619";
return 0;
}
static int max1619_probe(struct i2c_client *new_client,
const struct i2c_device_id *id)
{
struct max1619_data *data;
int err;
data = kzalloc(sizeof(struct max1619_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
/* We can fill in the remaining client fields */ i2c_set_clientdata(new_client, data);
strlcpy(new_client->name, name, I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_free;
/* Initialize the MAX1619 chip */ /* Initialize the MAX1619 chip */
max1619_init_client(new_client); max1619_init_client(new_client);
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &max1619_group))) if ((err = sysfs_create_group(&new_client->dev.kobj, &max1619_group)))
goto exit_detach; goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev); data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -318,8 +311,6 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -318,8 +311,6 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove_files: exit_remove_files:
sysfs_remove_group(&new_client->dev.kobj, &max1619_group); sysfs_remove_group(&new_client->dev.kobj, &max1619_group);
exit_detach:
i2c_detach_client(new_client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
...@@ -341,17 +332,13 @@ static void max1619_init_client(struct i2c_client *client) ...@@ -341,17 +332,13 @@ static void max1619_init_client(struct i2c_client *client)
config & 0xBF); /* run */ config & 0xBF); /* run */
} }
static int max1619_detach_client(struct i2c_client *client) static int max1619_remove(struct i2c_client *client)
{ {
struct max1619_data *data = i2c_get_clientdata(client); struct max1619_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &max1619_group); sysfs_remove_group(&client->dev.kobj, &max1619_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment