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
  ...
This commit is contained in:
Linus Torvalds 2008-07-16 11:47:35 -07:00
commit a3cf859321
50 changed files with 2143 additions and 2811 deletions

View File

@ -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

View File

@ -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.
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
------------- -------------

View File

@ -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.
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):

View File

@ -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
-------------- --------------

View File

@ -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,
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 {
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);
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[] = {
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)
/* 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)
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;
} }

View File

@ -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 {
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);
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 = {
.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)
|| (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)
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;
static int adm1021_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
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); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(client)))
goto error1;
/* 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)
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)
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;
} }

View File

@ -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 };
* 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 = {
*/ */
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);
* 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 = {
.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)
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)
} }
} 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)
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)
} 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); }
static int adm1025_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
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); 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 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)
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)
(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;
} }

View File

@ -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 {
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);
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 = {
.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,
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,
"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,
/* 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 @@ exitremove:
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)
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;
} }

View File

@ -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);
* 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 = {
*/ */
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 = {
* 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)
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)
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)
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;
} }

View File

@ -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 {
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);
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 = {
.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)
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)
* 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)
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;
} }

View File

@ -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 = {
/*** 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)
!= 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)
} 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)
} 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;
static int adm9240_probe(struct i2c_client *new_client,
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); mutex_init(&data->update_lock);
if ((err = i2c_attach_client(new_client)))
goto exit_free;
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)
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;
} }

View File

@ -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 {
}; };
/* 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 = {
.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)
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)
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:

View File

@ -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 {
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[] =
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,
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, adt7470_detect);
}
static int adt7470_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *client;
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)
/* 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)
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;
} }

View File

@ -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 {
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,21 +1053,43 @@ 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;
if (kind <= 0) {
int vendor, device, revision;
vendor = i2c_smbus_read_byte_data(client, ADT7473_REG_VENDOR);
if (vendor != ADT7473_VENDOR)
return -ENODEV;
device = i2c_smbus_read_byte_data(client, ADT7473_REG_DEVICE);
if (device != ADT7473_DEVICE)
return -ENODEV;
revision = i2c_smbus_read_byte_data(client,
ADT7473_REG_REVISION);
if (revision != ADT7473_REV_68 && revision != ADT7473_REV_69)
return -ENODEV;
} else
dev_dbg(&adapter->dev, "detection forced\n");
strlcpy(info->type, "adt7473", I2C_NAME_SIZE);
return 0;
}
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); data = kzalloc(sizeof(struct adt7473_data), GFP_KERNEL);
if (!data) { if (!data) {
@ -1064,45 +1097,9 @@ static int adt7473_detect(struct i2c_adapter *adapter, int address, int kind)
goto exit; goto exit;
} }
client = &data->client;
client->addr = address;
client->adapter = adapter;
client->driver = &adt7473_driver;
i2c_set_clientdata(client, data); i2c_set_clientdata(client, data);
mutex_init(&data->lock); mutex_init(&data->lock);
if (kind <= 0) {
int vendor, device, revision;
vendor = i2c_smbus_read_byte_data(client, ADT7473_REG_VENDOR);
if (vendor != ADT7473_VENDOR) {
err = -ENODEV;
goto exit_free;
}
device = i2c_smbus_read_byte_data(client, ADT7473_REG_DEVICE);
if (device != ADT7473_DEVICE) {
err = -ENODEV;
goto exit_free;
}
revision = i2c_smbus_read_byte_data(client,
ADT7473_REG_REVISION);
if (revision != ADT7473_REV_68 && revision != ADT7473_REV_69) {
err = -ENODEV;
goto exit_free;
}
} else
dev_dbg(&adapter->dev, "detection forced\n");
strlcpy(client->name, "adt7473", I2C_NAME_SIZE);
err = i2c_attach_client(client);
if (err)
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 ADT7473 chip */ /* Initialize the ADT7473 chip */
@ -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)
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;
} }

View File

@ -176,10 +176,8 @@ static u8 DIV_TO_REG(long val)
data is pointed to by client->data. The structure itself is data is pointed to by client->data. The structure itself is
dynamically allocated, at the same time the client itself is allocated. */ dynamically allocated, at the same time the client itself is allocated. */
struct asb100_data { struct asb100_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex lock; struct mutex lock;
enum chips type;
struct mutex update_lock; struct mutex update_lock;
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@ -206,18 +204,30 @@ struct asb100_data {
static int asb100_read_value(struct i2c_client *client, u16 reg); static int asb100_read_value(struct i2c_client *client, u16 reg);
static void asb100_write_value(struct i2c_client *client, u16 reg, u16 val); static void asb100_write_value(struct i2c_client *client, u16 reg, u16 val);
static int asb100_attach_adapter(struct i2c_adapter *adapter); static int asb100_probe(struct i2c_client *client,
static int asb100_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int asb100_detach_client(struct i2c_client *client); static int asb100_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static int asb100_remove(struct i2c_client *client);
static struct asb100_data *asb100_update_device(struct device *dev); static struct asb100_data *asb100_update_device(struct device *dev);
static void asb100_init_client(struct i2c_client *client); static void asb100_init_client(struct i2c_client *client);
static const struct i2c_device_id asb100_id[] = {
{ "asb100", asb100 },
{ }
};
MODULE_DEVICE_TABLE(i2c, asb100_id);
static struct i2c_driver asb100_driver = { static struct i2c_driver asb100_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "asb100", .name = "asb100",
}, },
.attach_adapter = asb100_attach_adapter, .probe = asb100_probe,
.detach_client = asb100_detach_client, .remove = asb100_remove,
.id_table = asb100_id,
.detect = asb100_detect,
.address_data = &addr_data,
}; };
/* 7 Voltages */ /* 7 Voltages */
@ -619,35 +629,13 @@ static const struct attribute_group asb100_group = {
.attrs = asb100_attributes, .attrs = asb100_attributes,
}; };
/* This function is called when: static int asb100_detect_subclients(struct i2c_client *client)
asb100_driver is inserted (when this module is loaded), for each
available adapter
when a new adapter is inserted (and asb100_driver is still present)
*/
static int asb100_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, asb100_detect);
}
static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
int kind, struct i2c_client *client)
{ {
int i, id, err; int i, id, err;
int address = client->addr;
unsigned short sc_addr[2];
struct asb100_data *data = i2c_get_clientdata(client); struct asb100_data *data = i2c_get_clientdata(client);
struct i2c_adapter *adapter = client->adapter;
data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!(data->lm75[0])) {
err = -ENOMEM;
goto ERROR_SC_0;
}
data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!(data->lm75[1])) {
err = -ENOMEM;
goto ERROR_SC_1;
}
id = i2c_adapter_id(adapter); id = i2c_adapter_id(adapter);
@ -665,37 +653,34 @@ static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
asb100_write_value(client, ASB100_REG_I2C_SUBADDR, asb100_write_value(client, ASB100_REG_I2C_SUBADDR,
(force_subclients[2] & 0x07) | (force_subclients[2] & 0x07) |
((force_subclients[3] & 0x07) << 4)); ((force_subclients[3] & 0x07) << 4));
data->lm75[0]->addr = force_subclients[2]; sc_addr[0] = force_subclients[2];
data->lm75[1]->addr = force_subclients[3]; sc_addr[1] = force_subclients[3];
} else { } else {
int val = asb100_read_value(client, ASB100_REG_I2C_SUBADDR); int val = asb100_read_value(client, ASB100_REG_I2C_SUBADDR);
data->lm75[0]->addr = 0x48 + (val & 0x07); sc_addr[0] = 0x48 + (val & 0x07);
data->lm75[1]->addr = 0x48 + ((val >> 4) & 0x07); sc_addr[1] = 0x48 + ((val >> 4) & 0x07);
} }
if (data->lm75[0]->addr == data->lm75[1]->addr) { if (sc_addr[0] == sc_addr[1]) {
dev_err(&client->dev, "duplicate addresses 0x%x " dev_err(&client->dev, "duplicate addresses 0x%x "
"for subclients\n", data->lm75[0]->addr); "for subclients\n", sc_addr[0]);
err = -ENODEV; err = -ENODEV;
goto ERROR_SC_2; goto ERROR_SC_2;
} }
for (i = 0; i <= 1; i++) { data->lm75[0] = i2c_new_dummy(adapter, sc_addr[0]);
i2c_set_clientdata(data->lm75[i], NULL); if (!data->lm75[0]) {
data->lm75[i]->adapter = adapter;
data->lm75[i]->driver = &asb100_driver;
strlcpy(data->lm75[i]->name, "asb100 subclient", I2C_NAME_SIZE);
}
if ((err = i2c_attach_client(data->lm75[0]))) {
dev_err(&client->dev, "subclient %d registration " dev_err(&client->dev, "subclient %d registration "
"at address 0x%x failed.\n", i, data->lm75[0]->addr); "at address 0x%x failed.\n", 1, sc_addr[0]);
err = -ENOMEM;
goto ERROR_SC_2; goto ERROR_SC_2;
} }
if ((err = i2c_attach_client(data->lm75[1]))) { data->lm75[1] = i2c_new_dummy(adapter, sc_addr[1]);
if (!data->lm75[1]) {
dev_err(&client->dev, "subclient %d registration " dev_err(&client->dev, "subclient %d registration "
"at address 0x%x failed.\n", i, data->lm75[1]->addr); "at address 0x%x failed.\n", 2, sc_addr[1]);
err = -ENOMEM;
goto ERROR_SC_3; goto ERROR_SC_3;
} }
@ -703,55 +688,31 @@ static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
/* Undo inits in case of errors */ /* Undo inits in case of errors */
ERROR_SC_3: ERROR_SC_3:
i2c_detach_client(data->lm75[0]); i2c_unregister_device(data->lm75[0]);
ERROR_SC_2: ERROR_SC_2:
kfree(data->lm75[1]);
ERROR_SC_1:
kfree(data->lm75[0]);
ERROR_SC_0:
return err; return err;
} }
static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) /* Return 0 if detection is successful, -ENODEV otherwise */
static int asb100_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
int err; struct i2c_adapter *adapter = client->adapter;
struct i2c_client *client;
struct asb100_data *data;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
pr_debug("asb100.o: detect failed, " pr_debug("asb100.o: detect failed, "
"smbus byte data not supported!\n"); "smbus byte data not supported!\n");
err = -ENODEV; return -ENODEV;
goto ERROR0;
} }
/* 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 asb100_{read,write}_value. */
if (!(data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL))) {
pr_debug("asb100.o: detect failed, kzalloc failed!\n");
err = -ENOMEM;
goto ERROR0;
}
client = &data->client;
mutex_init(&data->lock);
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &asb100_driver;
/* Now, we do the remaining detection. */
/* The chip may be stuck in some other bank than bank 0. This may /* The chip may be stuck in some other bank than bank 0. This may
make reading other information impossible. Specify a force=... or make reading other information impossible. Specify a force=... or
force_*=... parameter, and the chip will be reset to the right force_*=... parameter, and the chip will be reset to the right
bank. */ bank. */
if (kind < 0) { if (kind < 0) {
int val1 = asb100_read_value(client, ASB100_REG_BANK); int val1 = i2c_smbus_read_byte_data(client, ASB100_REG_BANK);
int val2 = asb100_read_value(client, ASB100_REG_CHIPMAN); int val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN);
/* If we're in bank 0 */ /* If we're in bank 0 */
if ((!(val1 & 0x07)) && if ((!(val1 & 0x07)) &&
@ -761,48 +722,60 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
((val1 & 0x80) && (val2 != 0x06)))) { ((val1 & 0x80) && (val2 != 0x06)))) {
pr_debug("asb100.o: detect failed, " pr_debug("asb100.o: detect failed, "
"bad chip id 0x%02x!\n", val2); "bad chip id 0x%02x!\n", val2);
err = -ENODEV; return -ENODEV;
goto ERROR1;
} }
} /* kind < 0 */ } /* kind < 0 */
/* We have either had a force parameter, or we have already detected /* We have either had a force parameter, or we have already detected
Winbond. Put it now into bank 0 and Vendor ID High Byte */ Winbond. Put it now into bank 0 and Vendor ID High Byte */
asb100_write_value(client, ASB100_REG_BANK, i2c_smbus_write_byte_data(client, ASB100_REG_BANK,
(asb100_read_value(client, ASB100_REG_BANK) & 0x78) | 0x80); (i2c_smbus_read_byte_data(client, ASB100_REG_BANK) & 0x78)
| 0x80);
/* Determine the chip type. */ /* Determine the chip type. */
if (kind <= 0) { if (kind <= 0) {
int val1 = asb100_read_value(client, ASB100_REG_WCHIPID); int val1 = i2c_smbus_read_byte_data(client, ASB100_REG_WCHIPID);
int val2 = asb100_read_value(client, ASB100_REG_CHIPMAN); int val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN);
if ((val1 == 0x31) && (val2 == 0x06)) if ((val1 == 0x31) && (val2 == 0x06))
kind = asb100; kind = asb100;
else { else {
if (kind == 0) if (kind == 0)
dev_warn(&client->dev, "ignoring " dev_warn(&adapter->dev, "ignoring "
"'force' parameter for unknown chip " "'force' parameter for unknown chip "
"at adapter %d, address 0x%02x.\n", "at adapter %d, address 0x%02x.\n",
i2c_adapter_id(adapter), address); i2c_adapter_id(adapter), client->addr);
err = -ENODEV; return -ENODEV;
goto ERROR1;
} }
} }
/* Fill in remaining client fields and put it into the global list */ strlcpy(info->type, "asb100", I2C_NAME_SIZE);
strlcpy(client->name, "asb100", I2C_NAME_SIZE);
data->type = kind; return 0;
}
static int asb100_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int err;
struct asb100_data *data;
data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL);
if (!data) {
pr_debug("asb100.o: probe failed, kzalloc failed!\n");
err = -ENOMEM;
goto ERROR0;
}
i2c_set_clientdata(client, data);
mutex_init(&data->lock);
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 ERROR1;
/* Attach secondary lm75 clients */ /* Attach secondary lm75 clients */
if ((err = asb100_detect_subclients(adapter, address, kind, err = asb100_detect_subclients(client);
client))) if (err)
goto ERROR2; goto ERROR1;
/* Initialize the chip */ /* Initialize the chip */
asb100_init_client(client); asb100_init_client(client);
@ -827,39 +800,25 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
ERROR4: ERROR4:
sysfs_remove_group(&client->dev.kobj, &asb100_group); sysfs_remove_group(&client->dev.kobj, &asb100_group);
ERROR3: ERROR3:
i2c_detach_client(data->lm75[1]); i2c_unregister_device(data->lm75[1]);
i2c_detach_client(data->lm75[0]); i2c_unregister_device(data->lm75[0]);
kfree(data->lm75[1]);
kfree(data->lm75[0]);
ERROR2:
i2c_detach_client(client);
ERROR1: ERROR1:
kfree(data); kfree(data);
ERROR0: ERROR0:
return err; return err;
} }
static int asb100_detach_client(struct i2c_client *client) static int asb100_remove(struct i2c_client *client)
{ {
struct asb100_data *data = i2c_get_clientdata(client); struct asb100_data *data = i2c_get_clientdata(client);
int err;
/* main client */ hwmon_device_unregister(data->hwmon_dev);
if (data) { sysfs_remove_group(&client->dev.kobj, &asb100_group);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &asb100_group);
}
if ((err = i2c_detach_client(client))) i2c_unregister_device(data->lm75[1]);
return err; i2c_unregister_device(data->lm75[0]);
/* main client */ kfree(data);
if (data)
kfree(data);
/* subclient */
else
kfree(client);
return 0; return 0;
} }

View File

@ -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 = {
}; };
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)
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 */
temp = vid_which_vrm();
if ((temp != 90) && (temp != 91)) {
dev_err(&adapter->dev, "atxp1: Not supporting VRM %d.%d\n",
temp / 10, temp % 10);
return -ENODEV;
}
strlcpy(info->type, "atxp1", I2C_NAME_SIZE);
return 0;
}
static int atxp1_probe(struct i2c_client *new_client,
const struct i2c_device_id *id)
{
struct atxp1_data *data;
int err;
data = kzalloc(sizeof(struct atxp1_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
} }
/* Get VRM */ /* Get VRM */
data->vrm = vid_which_vrm(); data->vrm = vid_which_vrm();
if ((data->vrm != 90) && (data->vrm != 91)) { i2c_set_clientdata(new_client, data);
dev_err(&new_client->dev, "Not supporting VRM %d.%d\n",
data->vrm / 10, data->vrm % 10);
goto exit_free;
}
strncpy(new_client->name, "atxp1", I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
err = i2c_attach_client(new_client);
if (err)
{
dev_err(&new_client->dev, "Attach client error.\n");
goto exit_free;
}
/* 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)
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) return 0;
dev_err(&client->dev, "Failed to detach client.\n");
else
kfree(data);
return err;
}; };
static int __init atxp1_init(void) static int __init atxp1_init(void)

View File

@ -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 {
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 = {
}; };
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,
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,
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;

View File

@ -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 {
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[] = {
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 = {
.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,
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)
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,
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, 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;
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)
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)
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);
} }

View File

@ -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);
* 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 = {
*/ */
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 = {
* 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,
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, fscher_detect);
}
static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
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)
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;
} }
/* Fill in the remaining client fields and put it into the strlcpy(info->type, "fscher", I2C_NAME_SIZE);
* global list */
strlcpy(new_client->name, "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;
}
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;
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)
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;
} }

View File

@ -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 = {
*/ */
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
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
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,
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,
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)
} }
} }
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)
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)
/* 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)
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)
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;
} }

View File

@ -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);
/* /*
* 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 = {
.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,
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, fscpos_detect);
}
static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
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)
!= 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)
/* 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)
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;
} }

View File

@ -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 {
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 = {
* 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)
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)
/* 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 @@ exit_remove_files:
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)
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;
} }

View File

@ -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 = {
* 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,
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, gl520_detect);
}
static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *client;
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)
((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)
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)
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;
} }

View File

@ -1,7 +1,7 @@
/* /*
* 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);
* 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 = {
*/ */
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 = {
* 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)
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)
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)
(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;
} }

View File

@ -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 {
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);
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 = {
.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)
|| 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)
|| ((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)
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;
} }

View File

@ -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 {
* 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);
* 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);
* 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,54 +446,47 @@ 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); }
static int lm80_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
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); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(client)))
goto error_free;
/* 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)
/* 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)
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;

View File

@ -1,7 +1,7 @@
/* /*
* 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[] = {
* 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 = {
*/ */
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 = {
* 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)
((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)
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)
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)
*/ */
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)
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;
} }

View File

@ -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 };
* 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 = {
*/ */
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);
* 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 = {
.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)
|| (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)
/* 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)
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)
} }
} }
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;
} }

View File

@ -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 = {
*/ */
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)
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,
struct i2c_board_info *info)
{ {
if (!(adapter->class & I2C_CLASS_HWMON)) struct i2c_adapter *adapter = new_client->adapter;
return 0; int address = new_client->addr;
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 lm90_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 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)
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)
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)
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)
/* 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)
} else if (kind == adt7461) { } else if (kind == adt7461) {
name = "adt7461"; name = "adt7461";
} }
strlcpy(info->type, name, I2C_NAME_SIZE);
/* We can fill in the remaining client fields */ return 0;
strlcpy(new_client->name, name, I2C_NAME_SIZE); }
data->valid = 0;
data->kind = kind; 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;
data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
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)
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)
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)
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;
} }

View File

@ -1,6 +1,6 @@
/* /*
* 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;
/* 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 = {
.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)
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)
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)
* 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)

View File

@ -200,7 +200,6 @@ struct block1_t {
* Client-specific data * Client-specific data
*/ */
struct lm93_data { struct lm93_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
@ -2501,45 +2500,14 @@ static void lm93_init_client(struct i2c_client *client)
"chip to signal ready!\n"); "chip to signal ready!\n");
} }
static int lm93_detect(struct i2c_adapter *adapter, int address, int kind) /* Return 0 if detection is successful, -ENODEV otherwise */
static int lm93_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
struct lm93_data *data; struct i2c_adapter *adapter = client->adapter;
struct i2c_client *client;
int err = -ENODEV, func; if (!i2c_check_functionality(adapter, LM93_SMBUS_FUNC_MIN))
void (*update)(struct lm93_data *, struct i2c_client *); return -ENODEV;
/* choose update routine based on bus capabilities */
func = i2c_get_functionality(adapter);
if ( ((LM93_SMBUS_FUNC_FULL & func) == LM93_SMBUS_FUNC_FULL) &&
(!disable_block) ) {
dev_dbg(&adapter->dev,"using SMBus block data transactions\n");
update = lm93_update_client_full;
} else if ((LM93_SMBUS_FUNC_MIN & func) == LM93_SMBUS_FUNC_MIN) {
dev_dbg(&adapter->dev,"disabled SMBus block data "
"transactions\n");
update = lm93_update_client_min;
} else {
dev_dbg(&adapter->dev,"detect failed, "
"smbus byte and/or word data not supported!\n");
goto err_out;
}
/* 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 lm78_{read,write}_value. */
if ( !(data = kzalloc(sizeof(struct lm93_data), GFP_KERNEL))) {
dev_dbg(&adapter->dev,"out of memory!\n");
err = -ENOMEM;
goto err_out;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &lm93_driver;
/* detection */ /* detection */
if (kind < 0) { if (kind < 0) {
@ -2548,7 +2516,7 @@ static int lm93_detect(struct i2c_adapter *adapter, int address, int kind)
if (mfr != 0x01) { if (mfr != 0x01) {
dev_dbg(&adapter->dev,"detect failed, " dev_dbg(&adapter->dev,"detect failed, "
"bad manufacturer id 0x%02x!\n", mfr); "bad manufacturer id 0x%02x!\n", mfr);
goto err_free; return -ENODEV;
} }
} }
@ -2563,31 +2531,61 @@ static int lm93_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind == 0) if (kind == 0)
dev_dbg(&adapter->dev, dev_dbg(&adapter->dev,
"(ignored 'force' parameter)\n"); "(ignored 'force' parameter)\n");
goto err_free; return -ENODEV;
} }
} }
/* fill in remaining client fields */ strlcpy(info->type, "lm93", I2C_NAME_SIZE);
strlcpy(client->name, "lm93", I2C_NAME_SIZE);
dev_dbg(&adapter->dev,"loading %s at %d,0x%02x\n", dev_dbg(&adapter->dev,"loading %s at %d,0x%02x\n",
client->name, i2c_adapter_id(client->adapter), client->name, i2c_adapter_id(client->adapter),
client->addr); client->addr);
return 0;
}
static int lm93_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct lm93_data *data;
int err, func;
void (*update)(struct lm93_data *, struct i2c_client *);
/* choose update routine based on bus capabilities */
func = i2c_get_functionality(client->adapter);
if (((LM93_SMBUS_FUNC_FULL & func) == LM93_SMBUS_FUNC_FULL) &&
(!disable_block)) {
dev_dbg(&client->dev, "using SMBus block data transactions\n");
update = lm93_update_client_full;
} else if ((LM93_SMBUS_FUNC_MIN & func) == LM93_SMBUS_FUNC_MIN) {
dev_dbg(&client->dev, "disabled SMBus block data "
"transactions\n");
update = lm93_update_client_min;
} else {
dev_dbg(&client->dev, "detect failed, "
"smbus byte and/or word data not supported!\n");
err = -ENODEV;
goto err_out;
}
data = kzalloc(sizeof(struct lm93_data), GFP_KERNEL);
if (!data) {
dev_dbg(&client->dev, "out of memory!\n");
err = -ENOMEM;
goto err_out;
}
i2c_set_clientdata(client, data);
/* housekeeping */ /* housekeeping */
data->valid = 0; data->valid = 0;
data->update = update; data->update = update;
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 err_free;
/* initialize the chip */ /* initialize the chip */
lm93_init_client(client); lm93_init_client(client);
err = sysfs_create_group(&client->dev.kobj, &lm93_attr_grp); err = sysfs_create_group(&client->dev.kobj, &lm93_attr_grp);
if (err) if (err)
goto err_detach; goto err_free;
/* Register hwmon driver class */ /* Register hwmon driver class */
data->hwmon_dev = hwmon_device_register(&client->dev); data->hwmon_dev = hwmon_device_register(&client->dev);
@ -2597,43 +2595,39 @@ static int lm93_detect(struct i2c_adapter *adapter, int address, int kind)
err = PTR_ERR(data->hwmon_dev); err = PTR_ERR(data->hwmon_dev);
dev_err(&client->dev, "error registering hwmon device.\n"); dev_err(&client->dev, "error registering hwmon device.\n");
sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp); sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp);
err_detach:
i2c_detach_client(client);
err_free: err_free:
kfree(data); kfree(data);
err_out: err_out:
return err; return err;
} }
/* This function is called when: static int lm93_remove(struct i2c_client *client)
* lm93_driver is inserted (when this module is loaded), for each
available adapter
* when a new adapter is inserted (and lm93_driver is still present) */
static int lm93_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_probe(adapter, &addr_data, lm93_detect);
}
static int lm93_detach_client(struct i2c_client *client)
{ {
struct lm93_data *data = i2c_get_clientdata(client); struct lm93_data *data = i2c_get_clientdata(client);
int err = 0;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp); sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp);
err = i2c_detach_client(client); kfree(data);
if (!err) return 0;
kfree(data);
return err;
} }
static const struct i2c_device_id lm93_id[] = {
{ "lm93", lm93 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm93_id);
static struct i2c_driver lm93_driver = { static struct i2c_driver lm93_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "lm93", .name = "lm93",
}, },
.attach_adapter = lm93_attach_adapter, .probe = lm93_probe,
.detach_client = lm93_detach_client, .remove = lm93_remove,
.id_table = lm93_id,
.detect = lm93_detect,
.address_data = &addr_data,
}; };
static int __init lm93_init(void) static int __init lm93_init(void)

View File

@ -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 = {
*/ */
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 = {
* 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,
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, 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 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)
|| 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)
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";
/* We can fill in the remaining client fields */ return 0;
strlcpy(new_client->name, name, I2C_NAME_SIZE); }
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;
}
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 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)
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)
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;
} }

View File

@ -104,22 +104,34 @@ I2C_CLIENT_INSMOD_1(max6650);
#define DIV_FROM_REG(reg) (1 << (reg & 7)) #define DIV_FROM_REG(reg) (1 << (reg & 7))
static int max6650_attach_adapter(struct i2c_adapter *adapter); static int max6650_probe(struct i2c_client *client,
static int max6650_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int max6650_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static int max6650_init_client(struct i2c_client *client); static int max6650_init_client(struct i2c_client *client);
static int max6650_detach_client(struct i2c_client *client); static int max6650_remove(struct i2c_client *client);
static struct max6650_data *max6650_update_device(struct device *dev); static struct max6650_data *max6650_update_device(struct device *dev);
/* /*
* Driver data (common to all clients) * Driver data (common to all clients)
*/ */
static const struct i2c_device_id max6650_id[] = {
{ "max6650", max6650 },
{ }
};
MODULE_DEVICE_TABLE(i2c, max6650_id);
static struct i2c_driver max6650_driver = { static struct i2c_driver max6650_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "max6650", .name = "max6650",
}, },
.attach_adapter = max6650_attach_adapter, .probe = max6650_probe,
.detach_client = max6650_detach_client, .remove = max6650_remove,
.id_table = max6650_id,
.detect = max6650_detect,
.address_data = &addr_data,
}; };
/* /*
@ -128,7 +140,6 @@ static struct i2c_driver max6650_driver = {
struct max6650_data struct max6650_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 */
@ -437,47 +448,21 @@ static struct attribute_group max6650_attr_grp = {
* Real code * Real code
*/ */
static int max6650_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
static int max6650_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
if (!(adapter->class & I2C_CLASS_HWMON)) { struct i2c_adapter *adapter = client->adapter;
dev_dbg(&adapter->dev, int address = client->addr;
"FATAL: max6650_attach_adapter class HWMON not set\n");
return 0;
}
return i2c_probe(adapter, &addr_data, max6650_detect);
}
/*
* The following function does more than just detection. If detection
* succeeds, it also registers the new chip.
*/
static int max6650_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *client;
struct max6650_data *data;
int err = -ENODEV;
dev_dbg(&adapter->dev, "max6650_detect called, kind = %d\n", kind); dev_dbg(&adapter->dev, "max6650_detect called, kind = %d\n", kind);
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_dbg(&adapter->dev, "max6650: I2C bus doesn't support " dev_dbg(&adapter->dev, "max6650: I2C bus doesn't support "
"byte read mode, skipping.\n"); "byte read mode, skipping.\n");
return 0; return -ENODEV;
} }
if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) {
dev_err(&adapter->dev, "max6650: out of memory.\n");
return -ENOMEM;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &max6650_driver;
/* /*
* Now we do the remaining detection. A negative kind means that * Now we do the remaining detection. A negative kind means that
* the driver was loaded with no force parameter (default), so we * the driver was loaded with no force parameter (default), so we
@ -501,28 +486,40 @@ static int max6650_detect(struct i2c_adapter *adapter, int address, int kind)
||(i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT) & 0xFC))) { ||(i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT) & 0xFC))) {
dev_dbg(&adapter->dev, dev_dbg(&adapter->dev,
"max6650: detection failed at 0x%02x.\n", address); "max6650: detection failed at 0x%02x.\n", address);
goto err_free; return -ENODEV;
} }
dev_info(&adapter->dev, "max6650: chip found at 0x%02x.\n", address); dev_info(&adapter->dev, "max6650: chip found at 0x%02x.\n", address);
strlcpy(client->name, "max6650", I2C_NAME_SIZE); strlcpy(info->type, "max6650", I2C_NAME_SIZE);
mutex_init(&data->update_lock);
if ((err = i2c_attach_client(client))) { return 0;
dev_err(&adapter->dev, "max6650: failed to attach client.\n"); }
goto err_free;
static int max6650_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct max6650_data *data;
int err;
if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) {
dev_err(&client->dev, "out of memory.\n");
return -ENOMEM;
} }
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
/* /*
* Initialize the max6650 chip * Initialize the max6650 chip
*/ */
if (max6650_init_client(client)) err = max6650_init_client(client);
goto err_detach; if (err)
goto err_free;
err = sysfs_create_group(&client->dev.kobj, &max6650_attr_grp); err = sysfs_create_group(&client->dev.kobj, &max6650_attr_grp);
if (err) if (err)
goto err_detach; goto err_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))
@ -531,24 +528,19 @@ static int max6650_detect(struct i2c_adapter *adapter, int address, int kind)
err = PTR_ERR(data->hwmon_dev); err = PTR_ERR(data->hwmon_dev);
dev_err(&client->dev, "error registering hwmon device.\n"); dev_err(&client->dev, "error registering hwmon device.\n");
sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp);
err_detach:
i2c_detach_client(client);
err_free: err_free:
kfree(data); kfree(data);
return err; return err;
} }
static int max6650_detach_client(struct i2c_client *client) static int max6650_remove(struct i2c_client *client)
{ {
struct max6650_data *data = i2c_get_clientdata(client); struct max6650_data *data = i2c_get_clientdata(client);
int err;
sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp);
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
err = i2c_detach_client(client); kfree(data);
if (!err) return 0;
kfree(data);
return err;
} }
static int max6650_init_client(struct i2c_client *client) static int max6650_init_client(struct i2c_client *client)

View File

@ -96,7 +96,6 @@ static inline int TEMP_FROM_REG(s8 val)
} }
struct smsc47m192_data { struct smsc47m192_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 */
@ -114,18 +113,29 @@ struct smsc47m192_data {
u8 vrm; u8 vrm;
}; };
static int smsc47m192_attach_adapter(struct i2c_adapter *adapter); static int smsc47m192_probe(struct i2c_client *client,
static int smsc47m192_detect(struct i2c_adapter *adapter, int address, const struct i2c_device_id *id);
int kind); static int smsc47m192_detect(struct i2c_client *client, int kind,
static int smsc47m192_detach_client(struct i2c_client *client); struct i2c_board_info *info);
static int smsc47m192_remove(struct i2c_client *client);
static struct smsc47m192_data *smsc47m192_update_device(struct device *dev); static struct smsc47m192_data *smsc47m192_update_device(struct device *dev);
static const struct i2c_device_id smsc47m192_id[] = {
{ "smsc47m192", smsc47m192 },
{ }
};
MODULE_DEVICE_TABLE(i2c, smsc47m192_id);
static struct i2c_driver smsc47m192_driver = { static struct i2c_driver smsc47m192_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "smsc47m192", .name = "smsc47m192",
}, },
.attach_adapter = smsc47m192_attach_adapter, .probe = smsc47m192_probe,
.detach_client = smsc47m192_detach_client, .remove = smsc47m192_remove,
.id_table = smsc47m192_id,
.detect = smsc47m192_detect,
.address_data = &addr_data,
}; };
/* Voltages */ /* Voltages */
@ -440,17 +450,6 @@ static const struct attribute_group smsc47m192_group_in4 = {
.attrs = smsc47m192_attributes_in4, .attrs = smsc47m192_attributes_in4,
}; };
/* This function is called when:
* smsc47m192_driver is inserted (when this module is loaded), for each
available adapter
* when a new adapter is inserted (and smsc47m192_driver is still present) */
static int smsc47m192_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, smsc47m192_detect);
}
static void smsc47m192_init_client(struct i2c_client *client) static void smsc47m192_init_client(struct i2c_client *client)
{ {
int i; int i;
@ -481,31 +480,15 @@ static void smsc47m192_init_client(struct i2c_client *client)
} }
} }
/* This function is called by i2c_probe */ /* Return 0 if detection is successful, -ENODEV otherwise */
static int smsc47m192_detect(struct i2c_adapter *adapter, int address, static int smsc47m192_detect(struct i2c_client *client, int kind,
int kind) struct i2c_board_info *info)
{ {
struct i2c_client *client; struct i2c_adapter *adapter = client->adapter;
struct smsc47m192_data *data; int version;
int err = 0;
int version, 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 smsc47m192_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &smsc47m192_driver;
if (kind == 0)
kind = smsc47m192;
/* Detection criteria from sensors_detect script */ /* Detection criteria from sensors_detect script */
if (kind < 0) { if (kind < 0) {
@ -523,26 +506,39 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
} else { } else {
dev_dbg(&adapter->dev, dev_dbg(&adapter->dev,
"SMSC47M192 detection failed at 0x%02x\n", "SMSC47M192 detection failed at 0x%02x\n",
address); client->addr);
goto exit_free; return -ENODEV;
} }
} }
/* Fill in the remaining client fields and put into the global list */ strlcpy(info->type, "smsc47m192", I2C_NAME_SIZE);
strlcpy(client->name, "smsc47m192", I2C_NAME_SIZE);
return 0;
}
static int smsc47m192_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct smsc47m192_data *data;
int config;
int err;
data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
data->vrm = vid_which_vrm(); data->vrm = vid_which_vrm();
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 SMSC47M192 chip */ /* Initialize the SMSC47M192 chip */
smsc47m192_init_client(client); smsc47m192_init_client(client);
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group))) if ((err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group)))
goto exit_detach; goto exit_free;
/* Pin 110 is either in4 (+12V) or VID4 */ /* Pin 110 is either in4 (+12V) or VID4 */
config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
@ -563,26 +559,20 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
exit_remove_files: exit_remove_files:
sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
exit_detach:
i2c_detach_client(client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int smsc47m192_detach_client(struct i2c_client *client) static int smsc47m192_remove(struct i2c_client *client)
{ {
struct smsc47m192_data *data = i2c_get_clientdata(client); struct smsc47m192_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, &smsc47m192_group); sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;

View File

@ -60,7 +60,6 @@ static const u8 THMC50_REG_TEMP_MAX[] = { 0x39, 0x37, 0x2B };
/* Each client has this additional data */ /* Each client has this additional data */
struct thmc50_data { struct thmc50_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
@ -77,17 +76,31 @@ struct thmc50_data {
u8 alarms; u8 alarms;
}; };
static int thmc50_attach_adapter(struct i2c_adapter *adapter); static int thmc50_detect(struct i2c_client *client, int kind,
static int thmc50_detach_client(struct i2c_client *client); struct i2c_board_info *info);
static int thmc50_probe(struct i2c_client *client,
const struct i2c_device_id *id);
static int thmc50_remove(struct i2c_client *client);
static void thmc50_init_client(struct i2c_client *client); static void thmc50_init_client(struct i2c_client *client);
static struct thmc50_data *thmc50_update_device(struct device *dev); static struct thmc50_data *thmc50_update_device(struct device *dev);
static const struct i2c_device_id thmc50_id[] = {
{ "adm1022", adm1022 },
{ "thmc50", thmc50 },
{ }
};
MODULE_DEVICE_TABLE(i2c, thmc50_id);
static struct i2c_driver thmc50_driver = { static struct i2c_driver thmc50_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "thmc50", .name = "thmc50",
}, },
.attach_adapter = thmc50_attach_adapter, .probe = thmc50_probe,
.detach_client = thmc50_detach_client, .remove = thmc50_remove,
.id_table = thmc50_id,
.detect = thmc50_detect,
.address_data = &addr_data,
}; };
static ssize_t show_analog_out(struct device *dev, static ssize_t show_analog_out(struct device *dev,
@ -250,39 +263,23 @@ static const struct attribute_group temp3_group = {
.attrs = temp3_attributes, .attrs = temp3_attributes,
}; };
static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind) /* Return 0 if detection is successful, -ENODEV otherwise */
static int thmc50_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
unsigned company; unsigned company;
unsigned revision; unsigned revision;
unsigned config; unsigned config;
struct i2c_client *client; struct i2c_adapter *adapter = client->adapter;
struct thmc50_data *data;
struct device *dev;
int err = 0; int err = 0;
const char *type_name; const char *type_name;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
pr_debug("thmc50: detect failed, " pr_debug("thmc50: detect failed, "
"smbus byte data not supported!\n"); "smbus byte data not supported!\n");
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 thmc50 registers. */
if (!(data = kzalloc(sizeof(struct thmc50_data), GFP_KERNEL))) {
pr_debug("thmc50: detect failed, kzalloc failed!\n");
err = -ENOMEM;
goto exit;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &thmc50_driver;
dev = &client->dev;
pr_debug("thmc50: Probing for THMC50 at 0x%2X on bus %d\n", pr_debug("thmc50: Probing for THMC50 at 0x%2X on bus %d\n",
client->addr, i2c_adapter_id(client->adapter)); client->addr, i2c_adapter_id(client->adapter));
@ -307,21 +304,22 @@ static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind)
} }
if (err == -ENODEV) { if (err == -ENODEV) {
pr_debug("thmc50: Detection of THMC50/ADM1022 failed\n"); pr_debug("thmc50: Detection of THMC50/ADM1022 failed\n");
goto exit_free; return err;
} }
data->type = kind;
if (kind == adm1022) { if (kind == adm1022) {
int id = i2c_adapter_id(client->adapter); int id = i2c_adapter_id(client->adapter);
int i; int i;
type_name = "adm1022"; type_name = "adm1022";
data->has_temp3 = (config >> 7) & 1; /* config MSB */
for (i = 0; i + 1 < adm1022_temp3_num; i += 2) for (i = 0; i + 1 < adm1022_temp3_num; i += 2)
if (adm1022_temp3[i] == id && if (adm1022_temp3[i] == id &&
adm1022_temp3[i + 1] == address) { adm1022_temp3[i + 1] == client->addr) {
/* enable 2nd remote temp */ /* enable 2nd remote temp */
data->has_temp3 = 1; config |= (1 << 7);
i2c_smbus_write_byte_data(client,
THMC50_REG_CONF,
config);
break; break;
} }
} else { } else {
@ -330,19 +328,33 @@ static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind)
pr_debug("thmc50: Detected %s (version %x, revision %x)\n", pr_debug("thmc50: Detected %s (version %x, revision %x)\n",
type_name, (revision >> 4) - 0xc, revision & 0xf); type_name, (revision >> 4) - 0xc, revision & 0xf);
/* Fill in the remaining client fields & put it into the global list */ strlcpy(info->type, type_name, I2C_NAME_SIZE);
strlcpy(client->name, type_name, 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 thmc50_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct thmc50_data *data;
int err;
data = kzalloc(sizeof(struct thmc50_data), GFP_KERNEL);
if (!data) {
pr_debug("thmc50: detect failed, kzalloc failed!\n");
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
data->type = id->driver_data;
mutex_init(&data->update_lock);
thmc50_init_client(client); thmc50_init_client(client);
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &thmc50_group))) if ((err = sysfs_create_group(&client->dev.kobj, &thmc50_group)))
goto exit_detach; goto exit_free;
/* Register ADM1022 sysfs hooks */ /* Register ADM1022 sysfs hooks */
if (data->has_temp3) if (data->has_temp3)
@ -364,34 +376,21 @@ exit_remove_sysfs:
sysfs_remove_group(&client->dev.kobj, &temp3_group); sysfs_remove_group(&client->dev.kobj, &temp3_group);
exit_remove_sysfs_thmc50: exit_remove_sysfs_thmc50:
sysfs_remove_group(&client->dev.kobj, &thmc50_group); sysfs_remove_group(&client->dev.kobj, &thmc50_group);
exit_detach:
i2c_detach_client(client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int thmc50_attach_adapter(struct i2c_adapter *adapter) static int thmc50_remove(struct i2c_client *client)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, thmc50_detect);
}
static int thmc50_detach_client(struct i2c_client *client)
{ {
struct thmc50_data *data = i2c_get_clientdata(client); struct thmc50_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, &thmc50_group); sysfs_remove_group(&client->dev.kobj, &thmc50_group);
if (data->has_temp3) if (data->has_temp3)
sysfs_remove_group(&client->dev.kobj, &temp3_group); sysfs_remove_group(&client->dev.kobj, &temp3_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
@ -412,8 +411,8 @@ static void thmc50_init_client(struct i2c_client *client)
} }
config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF);
config |= 0x1; /* start the chip if it is in standby mode */ config |= 0x1; /* start the chip if it is in standby mode */
if (data->has_temp3) if (data->type == adm1022 && (config & (1 << 7)))
config |= 0x80; /* enable 2nd remote temp */ data->has_temp3 = 1;
i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config); i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config);
} }

View File

@ -247,7 +247,6 @@ static u8 div_to_reg(int nr, long val)
} }
struct w83791d_data { struct w83791d_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
@ -286,9 +285,11 @@ struct w83791d_data {
u8 vrm; /* hwmon-vid */ u8 vrm; /* hwmon-vid */
}; };
static int w83791d_attach_adapter(struct i2c_adapter *adapter); static int w83791d_probe(struct i2c_client *client,
static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int w83791d_detach_client(struct i2c_client *client); static int w83791d_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static int w83791d_remove(struct i2c_client *client);
static int w83791d_read(struct i2c_client *client, u8 register); static int w83791d_read(struct i2c_client *client, u8 register);
static int w83791d_write(struct i2c_client *client, u8 register, u8 value); static int w83791d_write(struct i2c_client *client, u8 register, u8 value);
@ -300,12 +301,22 @@ static void w83791d_print_debug(struct w83791d_data *data, struct device *dev);
static void w83791d_init_client(struct i2c_client *client); static void w83791d_init_client(struct i2c_client *client);
static const struct i2c_device_id w83791d_id[] = {
{ "w83791d", w83791d },
{ }
};
MODULE_DEVICE_TABLE(i2c, w83791d_id);
static struct i2c_driver w83791d_driver = { static struct i2c_driver w83791d_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "w83791d", .name = "w83791d",
}, },
.attach_adapter = w83791d_attach_adapter, .probe = w83791d_probe,
.detach_client = w83791d_detach_client, .remove = w83791d_remove,
.id_table = w83791d_id,
.detect = w83791d_detect,
.address_data = &addr_data,
}; };
/* following are the sysfs callback functions */ /* following are the sysfs callback functions */
@ -905,49 +916,12 @@ static const struct attribute_group w83791d_group = {
.attrs = w83791d_attributes, .attrs = w83791d_attributes,
}; };
/* This function is called when:
* w83791d_driver is inserted (when this module is loaded), for each static int w83791d_detect_subclients(struct i2c_client *client)
available adapter
* when a new adapter is inserted (and w83791d_driver is still present) */
static int w83791d_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, w83791d_detect);
}
static int w83791d_create_subclient(struct i2c_adapter *adapter,
struct i2c_client *client, int addr,
struct i2c_client **sub_cli)
{
int err;
struct i2c_client *sub_client;
(*sub_cli) = sub_client =
kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!(sub_client)) {
return -ENOMEM;
}
sub_client->addr = 0x48 + addr;
i2c_set_clientdata(sub_client, NULL);
sub_client->adapter = adapter;
sub_client->driver = &w83791d_driver;
strlcpy(sub_client->name, "w83791d subclient", I2C_NAME_SIZE);
if ((err = i2c_attach_client(sub_client))) {
dev_err(&client->dev, "subclient registration "
"at address 0x%x failed\n", sub_client->addr);
kfree(sub_client);
return err;
}
return 0;
}
static int w83791d_detect_subclients(struct i2c_adapter *adapter, int address,
int kind, struct i2c_client *client)
{ {
struct i2c_adapter *adapter = client->adapter;
struct w83791d_data *data = i2c_get_clientdata(client); struct w83791d_data *data = i2c_get_clientdata(client);
int address = client->addr;
int i, id, err; int i, id, err;
u8 val; u8 val;
@ -971,10 +945,7 @@ static int w83791d_detect_subclients(struct i2c_adapter *adapter, int address,
val = w83791d_read(client, W83791D_REG_I2C_SUBADDR); val = w83791d_read(client, W83791D_REG_I2C_SUBADDR);
if (!(val & 0x08)) { if (!(val & 0x08)) {
err = w83791d_create_subclient(adapter, client, data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7));
val & 0x7, &data->lm75[0]);
if (err < 0)
goto error_sc_0;
} }
if (!(val & 0x80)) { if (!(val & 0x80)) {
if ((data->lm75[0] != NULL) && if ((data->lm75[0] != NULL) &&
@ -986,10 +957,8 @@ static int w83791d_detect_subclients(struct i2c_adapter *adapter, int address,
err = -ENODEV; err = -ENODEV;
goto error_sc_1; goto error_sc_1;
} }
err = w83791d_create_subclient(adapter, client, data->lm75[1] = i2c_new_dummy(adapter,
(val >> 4) & 0x7, &data->lm75[1]); 0x48 + ((val >> 4) & 0x7));
if (err < 0)
goto error_sc_1;
} }
return 0; return 0;
@ -997,53 +966,31 @@ static int w83791d_detect_subclients(struct i2c_adapter *adapter, int address,
/* Undo inits in case of errors */ /* Undo inits in case of errors */
error_sc_1: error_sc_1:
if (data->lm75[0] != NULL) { if (data->lm75[0] != NULL)
i2c_detach_client(data->lm75[0]); i2c_unregister_device(data->lm75[0]);
kfree(data->lm75[0]);
}
error_sc_0: error_sc_0:
return err; return err;
} }
static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind) /* Return 0 if detection is successful, -ENODEV otherwise */
static int w83791d_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
struct i2c_client *client; struct i2c_adapter *adapter = client->adapter;
struct device *dev; int val1, val2;
struct w83791d_data *data; unsigned short address = client->addr;
int i, val1, val2;
int err = 0;
const char *client_name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
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 w83791d_{read,write}_value. */
if (!(data = kzalloc(sizeof(struct w83791d_data), GFP_KERNEL))) {
err = -ENOMEM;
goto error0;
}
client = &data->client;
dev = &client->dev;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &w83791d_driver;
mutex_init(&data->update_lock);
/* Now, we do the remaining detection. */
/* The w83791d may be stuck in some other bank than bank 0. This may /* The w83791d may be stuck in some other bank than bank 0. This may
make reading other information impossible. Specify a force=... make reading other information impossible. Specify a force=...
parameter, and the Winbond will be reset to the right bank. */ parameter, and the Winbond will be reset to the right bank. */
if (kind < 0) { if (kind < 0) {
if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80) { if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80) {
dev_dbg(dev, "Detection failed at step 1\n"); return -ENODEV;
goto error1;
} }
val1 = w83791d_read(client, W83791D_REG_BANK); val1 = w83791d_read(client, W83791D_REG_BANK);
val2 = w83791d_read(client, W83791D_REG_CHIPMAN); val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
@ -1052,15 +999,13 @@ static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind)
/* yes it is Bank0 */ /* yes it is Bank0 */
if (((!(val1 & 0x80)) && (val2 != 0xa3)) || if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
((val1 & 0x80) && (val2 != 0x5c))) { ((val1 & 0x80) && (val2 != 0x5c))) {
dev_dbg(dev, "Detection failed at step 2\n"); return -ENODEV;
goto error1;
} }
} }
/* If Winbond chip, address of chip and W83791D_REG_I2C_ADDR /* If Winbond chip, address of chip and W83791D_REG_I2C_ADDR
should match */ should match */
if (w83791d_read(client, W83791D_REG_I2C_ADDR) != address) { if (w83791d_read(client, W83791D_REG_I2C_ADDR) != address) {
dev_dbg(dev, "Detection failed at step 3\n"); return -ENODEV;
goto error1;
} }
} }
@ -1075,30 +1020,33 @@ static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind)
/* get vendor ID */ /* get vendor ID */
val2 = w83791d_read(client, W83791D_REG_CHIPMAN); val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
if (val2 != 0x5c) { /* the vendor is NOT Winbond */ if (val2 != 0x5c) { /* the vendor is NOT Winbond */
dev_dbg(dev, "Detection failed at step 4\n"); return -ENODEV;
goto error1;
} }
val1 = w83791d_read(client, W83791D_REG_WCHIPID); val1 = w83791d_read(client, W83791D_REG_WCHIPID);
if (val1 == 0x71) { if (val1 == 0x71) {
kind = w83791d; kind = w83791d;
} else { } else {
if (kind == 0) if (kind == 0)
dev_warn(dev, dev_warn(&adapter->dev,
"w83791d: Ignoring 'force' parameter " "w83791d: Ignoring 'force' parameter "
"for unknown chip at adapter %d, " "for unknown chip at adapter %d, "
"address 0x%02x\n", "address 0x%02x\n",
i2c_adapter_id(adapter), address); i2c_adapter_id(adapter), address);
goto error1; return -ENODEV;
} }
} }
if (kind == w83791d) { strlcpy(info->type, "w83791d", I2C_NAME_SIZE);
client_name = "w83791d";
} else { return 0;
dev_err(dev, "w83791d: Internal error: unknown kind (%d)?!?\n", }
kind);
goto error1; static int w83791d_probe(struct i2c_client *client,
} const struct i2c_device_id *id)
{
struct w83791d_data *data;
struct device *dev = &client->dev;
int i, val1, err;
#ifdef DEBUG #ifdef DEBUG
val1 = w83791d_read(client, W83791D_REG_DID_VID4); val1 = w83791d_read(client, W83791D_REG_DID_VID4);
@ -1106,16 +1054,19 @@ static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind)
(val1 >> 5) & 0x07, (val1 >> 1) & 0x0f, val1); (val1 >> 5) & 0x07, (val1 >> 1) & 0x0f, val1);
#endif #endif
/* Fill in the remaining client fields and put into the global list */ data = kzalloc(sizeof(struct w83791d_data), GFP_KERNEL);
strlcpy(client->name, client_name, I2C_NAME_SIZE); if (!data) {
err = -ENOMEM;
goto error0;
}
/* Tell the I2C layer a new client has arrived */ i2c_set_clientdata(client, data);
if ((err = i2c_attach_client(client))) mutex_init(&data->update_lock);
err = w83791d_detect_subclients(client);
if (err)
goto error1; goto error1;
if ((err = w83791d_detect_subclients(adapter, address, kind, client)))
goto error2;
/* Initialize the chip */ /* Initialize the chip */
w83791d_init_client(client); w83791d_init_client(client);
@ -1141,43 +1092,29 @@ static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind)
error4: error4:
sysfs_remove_group(&client->dev.kobj, &w83791d_group); sysfs_remove_group(&client->dev.kobj, &w83791d_group);
error3: error3:
if (data->lm75[0] != NULL) { if (data->lm75[0] != NULL)
i2c_detach_client(data->lm75[0]); i2c_unregister_device(data->lm75[0]);
kfree(data->lm75[0]); if (data->lm75[1] != NULL)
} i2c_unregister_device(data->lm75[1]);
if (data->lm75[1] != NULL) {
i2c_detach_client(data->lm75[1]);
kfree(data->lm75[1]);
}
error2:
i2c_detach_client(client);
error1: error1:
kfree(data); kfree(data);
error0: error0:
return err; return err;
} }
static int w83791d_detach_client(struct i2c_client *client) static int w83791d_remove(struct i2c_client *client)
{ {
struct w83791d_data *data = i2c_get_clientdata(client); struct w83791d_data *data = i2c_get_clientdata(client);
int err;
/* main client */ hwmon_device_unregister(data->hwmon_dev);
if (data) { sysfs_remove_group(&client->dev.kobj, &w83791d_group);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &w83791d_group);
}
if ((err = i2c_detach_client(client))) if (data->lm75[0] != NULL)
return err; i2c_unregister_device(data->lm75[0]);
if (data->lm75[1] != NULL)
/* main client */ i2c_unregister_device(data->lm75[1]);
if (data)
kfree(data);
/* subclient */
else
kfree(client);
kfree(data);
return 0; return 0;
} }

View File

@ -267,9 +267,7 @@ DIV_TO_REG(long val)
} }
struct w83792d_data { struct w83792d_data {
struct i2c_client client;
struct device *hwmon_dev; struct device *hwmon_dev;
enum chips type;
struct mutex update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
@ -299,9 +297,11 @@ struct w83792d_data {
u8 sf2_levels[3][4]; /* Smart FanII: Fan1,2,3 duty cycle levels */ u8 sf2_levels[3][4]; /* Smart FanII: Fan1,2,3 duty cycle levels */
}; };
static int w83792d_attach_adapter(struct i2c_adapter *adapter); static int w83792d_probe(struct i2c_client *client,
static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int w83792d_detach_client(struct i2c_client *client); static int w83792d_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static int w83792d_remove(struct i2c_client *client);
static struct w83792d_data *w83792d_update_device(struct device *dev); static struct w83792d_data *w83792d_update_device(struct device *dev);
#ifdef DEBUG #ifdef DEBUG
@ -310,12 +310,22 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev);
static void w83792d_init_client(struct i2c_client *client); static void w83792d_init_client(struct i2c_client *client);
static const struct i2c_device_id w83792d_id[] = {
{ "w83792d", w83792d },
{ }
};
MODULE_DEVICE_TABLE(i2c, w83792d_id);
static struct i2c_driver w83792d_driver = { static struct i2c_driver w83792d_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "w83792d", .name = "w83792d",
}, },
.attach_adapter = w83792d_attach_adapter, .probe = w83792d_probe,
.detach_client = w83792d_detach_client, .remove = w83792d_remove,
.id_table = w83792d_id,
.detect = w83792d_detect,
.address_data = &addr_data,
}; };
static inline long in_count_from_reg(int nr, struct w83792d_data *data) static inline long in_count_from_reg(int nr, struct w83792d_data *data)
@ -864,53 +874,14 @@ store_sf2_level(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
/* This function is called when:
* w83792d_driver is inserted (when this module is loaded), for each
available adapter
* when a new adapter is inserted (and w83792d_driver is still present) */
static int
w83792d_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, w83792d_detect);
}
static int static int
w83792d_create_subclient(struct i2c_adapter *adapter, w83792d_detect_subclients(struct i2c_client *new_client)
struct i2c_client *new_client, int addr,
struct i2c_client **sub_cli)
{
int err;
struct i2c_client *sub_client;
(*sub_cli) = sub_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!(sub_client)) {
return -ENOMEM;
}
sub_client->addr = 0x48 + addr;
i2c_set_clientdata(sub_client, NULL);
sub_client->adapter = adapter;
sub_client->driver = &w83792d_driver;
sub_client->flags = 0;
strlcpy(sub_client->name, "w83792d subclient", I2C_NAME_SIZE);
if ((err = i2c_attach_client(sub_client))) {
dev_err(&new_client->dev, "subclient registration "
"at address 0x%x failed\n", sub_client->addr);
kfree(sub_client);
return err;
}
return 0;
}
static int
w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
struct i2c_client *new_client)
{ {
int i, id, err; int i, id, err;
int address = new_client->addr;
u8 val; u8 val;
struct i2c_adapter *adapter = new_client->adapter;
struct w83792d_data *data = i2c_get_clientdata(new_client); struct w83792d_data *data = i2c_get_clientdata(new_client);
id = i2c_adapter_id(adapter); id = i2c_adapter_id(adapter);
@ -932,10 +903,7 @@ w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR); val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR);
if (!(val & 0x08)) { if (!(val & 0x08)) {
err = w83792d_create_subclient(adapter, new_client, val & 0x7, data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7));
&data->lm75[0]);
if (err < 0)
goto ERROR_SC_0;
} }
if (!(val & 0x80)) { if (!(val & 0x80)) {
if ((data->lm75[0] != NULL) && if ((data->lm75[0] != NULL) &&
@ -945,10 +913,8 @@ w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
err = -ENODEV; err = -ENODEV;
goto ERROR_SC_1; goto ERROR_SC_1;
} }
err = w83792d_create_subclient(adapter, new_client, data->lm75[1] = i2c_new_dummy(adapter,
(val >> 4) & 0x7, &data->lm75[1]); 0x48 + ((val >> 4) & 0x7));
if (err < 0)
goto ERROR_SC_1;
} }
return 0; return 0;
@ -956,10 +922,8 @@ w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
/* Undo inits in case of errors */ /* Undo inits in case of errors */
ERROR_SC_1: ERROR_SC_1:
if (data->lm75[0] != NULL) { if (data->lm75[0] != NULL)
i2c_detach_client(data->lm75[0]); i2c_unregister_device(data->lm75[0]);
kfree(data->lm75[0]);
}
ERROR_SC_0: ERROR_SC_0:
return err; return err;
} }
@ -1294,47 +1258,25 @@ static const struct attribute_group w83792d_group = {
.attrs = w83792d_attributes, .attrs = w83792d_attributes,
}; };
/* Return 0 if detection is successful, -ENODEV otherwise */
static int static int
w83792d_detect(struct i2c_adapter *adapter, int address, int kind) w83792d_detect(struct i2c_client *client, int kind, struct i2c_board_info *info)
{ {
int i = 0, val1 = 0, val2; struct i2c_adapter *adapter = client->adapter;
struct i2c_client *client; int val1, val2;
struct device *dev; unsigned short address = client->addr;
struct w83792d_data *data;
int err = 0;
const char *client_name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
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 w83792d_{read,write}_value. */
if (!(data = kzalloc(sizeof(struct w83792d_data), GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR0;
}
client = &data->client;
dev = &client->dev;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &w83792d_driver;
client->flags = 0;
/* Now, we do the remaining detection. */
/* The w83792d may be stuck in some other bank than bank 0. This may /* The w83792d may be stuck in some other bank than bank 0. This may
make reading other information impossible. Specify a force=... or make reading other information impossible. Specify a force=... or
force_*=... parameter, and the Winbond will be reset to the right force_*=... parameter, and the Winbond will be reset to the right
bank. */ bank. */
if (kind < 0) { if (kind < 0) {
if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) { if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) {
dev_dbg(dev, "Detection failed at step 1\n"); return -ENODEV;
goto ERROR1;
} }
val1 = w83792d_read_value(client, W83792D_REG_BANK); val1 = w83792d_read_value(client, W83792D_REG_BANK);
val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN);
@ -1342,16 +1284,14 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
if (!(val1 & 0x07)) { /* is Bank0 */ if (!(val1 & 0x07)) { /* is Bank0 */
if (((!(val1 & 0x80)) && (val2 != 0xa3)) || if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
((val1 & 0x80) && (val2 != 0x5c))) { ((val1 & 0x80) && (val2 != 0x5c))) {
dev_dbg(dev, "Detection failed at step 2\n"); return -ENODEV;
goto ERROR1;
} }
} }
/* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR
should match */ should match */
if (w83792d_read_value(client, if (w83792d_read_value(client,
W83792D_REG_I2C_ADDR) != address) { W83792D_REG_I2C_ADDR) != address) {
dev_dbg(dev, "Detection failed at step 3\n"); return -ENODEV;
goto ERROR1;
} }
} }
@ -1367,45 +1307,48 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
/* get vendor ID */ /* get vendor ID */
val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN);
if (val2 != 0x5c) { /* the vendor is NOT Winbond */ if (val2 != 0x5c) { /* the vendor is NOT Winbond */
goto ERROR1; return -ENODEV;
} }
val1 = w83792d_read_value(client, W83792D_REG_WCHIPID); val1 = w83792d_read_value(client, W83792D_REG_WCHIPID);
if (val1 == 0x7a) { if (val1 == 0x7a) {
kind = w83792d; kind = w83792d;
} else { } else {
if (kind == 0) if (kind == 0)
dev_warn(dev, dev_warn(&adapter->dev,
"w83792d: Ignoring 'force' parameter for" "w83792d: Ignoring 'force' parameter for"
" unknown chip at adapter %d, address" " unknown chip at adapter %d, address"
" 0x%02x\n", i2c_adapter_id(adapter), " 0x%02x\n", i2c_adapter_id(adapter),
address); address);
goto ERROR1; return -ENODEV;
} }
} }
if (kind == w83792d) { strlcpy(info->type, "w83792d", I2C_NAME_SIZE);
client_name = "w83792d";
} else { return 0;
dev_err(dev, "w83792d: Internal error: unknown kind (%d)?!?\n", }
kind);
goto ERROR1; static int
w83792d_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct w83792d_data *data;
struct device *dev = &client->dev;
int i, val1, err;
data = kzalloc(sizeof(struct w83792d_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto ERROR0;
} }
/* Fill in the remaining client fields and put into the global list */ i2c_set_clientdata(client, data);
strlcpy(client->name, client_name, I2C_NAME_SIZE);
data->type = kind;
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 */ err = w83792d_detect_subclients(client);
if ((err = i2c_attach_client(client))) if (err)
goto ERROR1; goto ERROR1;
if ((err = w83792d_detect_subclients(adapter, address,
kind, client)))
goto ERROR2;
/* Initialize the chip */ /* Initialize the chip */
w83792d_init_client(client); w83792d_init_client(client);
@ -1457,16 +1400,10 @@ exit_remove_files:
for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++)
sysfs_remove_group(&dev->kobj, &w83792d_group_fan[i]); sysfs_remove_group(&dev->kobj, &w83792d_group_fan[i]);
ERROR3: ERROR3:
if (data->lm75[0] != NULL) { if (data->lm75[0] != NULL)
i2c_detach_client(data->lm75[0]); i2c_unregister_device(data->lm75[0]);
kfree(data->lm75[0]); if (data->lm75[1] != NULL)
} i2c_unregister_device(data->lm75[1]);
if (data->lm75[1] != NULL) {
i2c_detach_client(data->lm75[1]);
kfree(data->lm75[1]);
}
ERROR2:
i2c_detach_client(client);
ERROR1: ERROR1:
kfree(data); kfree(data);
ERROR0: ERROR0:
@ -1474,30 +1411,23 @@ ERROR0:
} }
static int static int
w83792d_detach_client(struct i2c_client *client) w83792d_remove(struct i2c_client *client)
{ {
struct w83792d_data *data = i2c_get_clientdata(client); struct w83792d_data *data = i2c_get_clientdata(client);
int err, i; int i;
/* main client */ hwmon_device_unregister(data->hwmon_dev);
if (data) { sysfs_remove_group(&client->dev.kobj, &w83792d_group);
hwmon_device_unregister(data->hwmon_dev); for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++)
sysfs_remove_group(&client->dev.kobj, &w83792d_group); sysfs_remove_group(&client->dev.kobj,
for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) &w83792d_group_fan[i]);
sysfs_remove_group(&client->dev.kobj,
&w83792d_group_fan[i]);
}
if ((err = i2c_detach_client(client))) if (data->lm75[0] != NULL)
return err; i2c_unregister_device(data->lm75[0]);
if (data->lm75[1] != NULL)
/* main client */ i2c_unregister_device(data->lm75[1]);
if (data)
kfree(data);
/* subclient */
else
kfree(client);
kfree(data);
return 0; return 0;
} }

View File

@ -179,7 +179,6 @@ static inline s8 TEMP_TO_REG(long val, s8 min, s8 max)
} }
struct w83793_data { struct w83793_data {
struct i2c_client client;
struct i2c_client *lm75[2]; struct i2c_client *lm75[2];
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
@ -226,19 +225,31 @@ struct w83793_data {
static u8 w83793_read_value(struct i2c_client *client, u16 reg); static u8 w83793_read_value(struct i2c_client *client, u16 reg);
static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value); static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value);
static int w83793_attach_adapter(struct i2c_adapter *adapter); static int w83793_probe(struct i2c_client *client,
static int w83793_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int w83793_detach_client(struct i2c_client *client); static int w83793_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static int w83793_remove(struct i2c_client *client);
static void w83793_init_client(struct i2c_client *client); static void w83793_init_client(struct i2c_client *client);
static void w83793_update_nonvolatile(struct device *dev); static void w83793_update_nonvolatile(struct device *dev);
static struct w83793_data *w83793_update_device(struct device *dev); static struct w83793_data *w83793_update_device(struct device *dev);
static const struct i2c_device_id w83793_id[] = {
{ "w83793", w83793 },
{ }
};
MODULE_DEVICE_TABLE(i2c, w83793_id);
static struct i2c_driver w83793_driver = { static struct i2c_driver w83793_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "w83793", .name = "w83793",
}, },
.attach_adapter = w83793_attach_adapter, .probe = w83793_probe,
.detach_client = w83793_detach_client, .remove = w83793_remove,
.id_table = w83793_id,
.detect = w83793_detect,
.address_data = &addr_data,
}; };
static ssize_t static ssize_t
@ -1053,89 +1064,51 @@ static void w83793_init_client(struct i2c_client *client)
} }
static int w83793_attach_adapter(struct i2c_adapter *adapter) static int w83793_remove(struct i2c_client *client)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, w83793_detect);
}
static int w83793_detach_client(struct i2c_client *client)
{ {
struct w83793_data *data = i2c_get_clientdata(client); struct w83793_data *data = i2c_get_clientdata(client);
struct device *dev = &client->dev; struct device *dev = &client->dev;
int err, i; int i;
/* main client */ hwmon_device_unregister(data->hwmon_dev);
if (data) {
hwmon_device_unregister(data->hwmon_dev);
for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++)
device_remove_file(dev, device_remove_file(dev,
&w83793_sensor_attr_2[i].dev_attr); &w83793_sensor_attr_2[i].dev_attr);
for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
device_remove_file(dev, &sda_single_files[i].dev_attr); device_remove_file(dev, &sda_single_files[i].dev_attr);
for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) for (i = 0; i < ARRAY_SIZE(w83793_vid); i++)
device_remove_file(dev, &w83793_vid[i].dev_attr); device_remove_file(dev, &w83793_vid[i].dev_attr);
device_remove_file(dev, &dev_attr_vrm); device_remove_file(dev, &dev_attr_vrm);
for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++) for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
device_remove_file(dev, &w83793_left_fan[i].dev_attr); device_remove_file(dev, &w83793_left_fan[i].dev_attr);
for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++) for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++)
device_remove_file(dev, &w83793_left_pwm[i].dev_attr); device_remove_file(dev, &w83793_left_pwm[i].dev_attr);
for (i = 0; i < ARRAY_SIZE(w83793_temp); i++) for (i = 0; i < ARRAY_SIZE(w83793_temp); i++)
device_remove_file(dev, &w83793_temp[i].dev_attr); device_remove_file(dev, &w83793_temp[i].dev_attr);
}
if ((err = i2c_detach_client(client))) if (data->lm75[0] != NULL)
return err; i2c_unregister_device(data->lm75[0]);
if (data->lm75[1] != NULL)
i2c_unregister_device(data->lm75[1]);
/* main client */ kfree(data);
if (data)
kfree(data);
/* subclient */
else
kfree(client);
return 0; return 0;
} }
static int static int
w83793_create_subclient(struct i2c_adapter *adapter, w83793_detect_subclients(struct i2c_client *client)
struct i2c_client *client, int addr,
struct i2c_client **sub_cli)
{
int err = 0;
struct i2c_client *sub_client;
(*sub_cli) = sub_client =
kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!(sub_client)) {
return -ENOMEM;
}
sub_client->addr = 0x48 + addr;
i2c_set_clientdata(sub_client, NULL);
sub_client->adapter = adapter;
sub_client->driver = &w83793_driver;
strlcpy(sub_client->name, "w83793 subclient", I2C_NAME_SIZE);
if ((err = i2c_attach_client(sub_client))) {
dev_err(&client->dev, "subclient registration "
"at address 0x%x failed\n", sub_client->addr);
kfree(sub_client);
}
return err;
}
static int
w83793_detect_subclients(struct i2c_adapter *adapter, int address,
int kind, struct i2c_client *client)
{ {
int i, id, err; int i, id, err;
int address = client->addr;
u8 tmp; u8 tmp;
struct i2c_adapter *adapter = client->adapter;
struct w83793_data *data = i2c_get_clientdata(client); struct w83793_data *data = i2c_get_clientdata(client);
id = i2c_adapter_id(adapter); id = i2c_adapter_id(adapter);
@ -1158,11 +1131,7 @@ w83793_detect_subclients(struct i2c_adapter *adapter, int address,
tmp = w83793_read_value(client, W83793_REG_I2C_SUBADDR); tmp = w83793_read_value(client, W83793_REG_I2C_SUBADDR);
if (!(tmp & 0x08)) { if (!(tmp & 0x08)) {
err = data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (tmp & 0x7));
w83793_create_subclient(adapter, client, tmp & 0x7,
&data->lm75[0]);
if (err < 0)
goto ERROR_SC_0;
} }
if (!(tmp & 0x80)) { if (!(tmp & 0x80)) {
if ((data->lm75[0] != NULL) if ((data->lm75[0] != NULL)
@ -1173,10 +1142,8 @@ w83793_detect_subclients(struct i2c_adapter *adapter, int address,
err = -ENODEV; err = -ENODEV;
goto ERROR_SC_1; goto ERROR_SC_1;
} }
err = w83793_create_subclient(adapter, client, data->lm75[1] = i2c_new_dummy(adapter,
(tmp >> 4) & 0x7, &data->lm75[1]); 0x48 + ((tmp >> 4) & 0x7));
if (err < 0)
goto ERROR_SC_1;
} }
return 0; return 0;
@ -1184,69 +1151,44 @@ w83793_detect_subclients(struct i2c_adapter *adapter, int address,
/* Undo inits in case of errors */ /* Undo inits in case of errors */
ERROR_SC_1: ERROR_SC_1:
if (data->lm75[0] != NULL) { if (data->lm75[0] != NULL)
i2c_detach_client(data->lm75[0]); i2c_unregister_device(data->lm75[0]);
kfree(data->lm75[0]);
}
ERROR_SC_0: ERROR_SC_0:
return err; return err;
} }
static int w83793_detect(struct i2c_adapter *adapter, int address, int kind) /* Return 0 if detection is successful, -ENODEV otherwise */
static int w83793_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
int i; u8 tmp, bank;
u8 tmp, val; struct i2c_adapter *adapter = client->adapter;
struct i2c_client *client; unsigned short address = client->addr;
struct device *dev;
struct w83793_data *data;
int files_fan = ARRAY_SIZE(w83793_left_fan) / 7;
int files_pwm = ARRAY_SIZE(w83793_left_pwm) / 5;
int files_temp = ARRAY_SIZE(w83793_temp) / 6;
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 bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL);
client structure, even though we cannot fill it completely yet.
But it allows us to access w83793_{read,write}_value. */
if (!(data = kzalloc(sizeof(struct w83793_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
dev = &client->dev;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &w83793_driver;
data->bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL);
/* Now, we do the remaining detection. */
if (kind < 0) { if (kind < 0) {
tmp = data->bank & 0x80 ? 0x5c : 0xa3; tmp = bank & 0x80 ? 0x5c : 0xa3;
/* Check Winbond vendor ID */ /* Check Winbond vendor ID */
if (tmp != i2c_smbus_read_byte_data(client, if (tmp != i2c_smbus_read_byte_data(client,
W83793_REG_VENDORID)) { W83793_REG_VENDORID)) {
pr_debug("w83793: Detection failed at check " pr_debug("w83793: Detection failed at check "
"vendor id\n"); "vendor id\n");
err = -ENODEV; return -ENODEV;
goto free_mem;
} }
/* If Winbond chip, address of chip and W83793_REG_I2C_ADDR /* If Winbond chip, address of chip and W83793_REG_I2C_ADDR
should match */ should match */
if ((data->bank & 0x07) == 0 if ((bank & 0x07) == 0
&& i2c_smbus_read_byte_data(client, W83793_REG_I2C_ADDR) != && i2c_smbus_read_byte_data(client, W83793_REG_I2C_ADDR) !=
(address << 1)) { (address << 1)) {
pr_debug("w83793: Detection failed at check " pr_debug("w83793: Detection failed at check "
"i2c addr\n"); "i2c addr\n");
err = -ENODEV; return -ENODEV;
goto free_mem;
} }
} }
@ -1255,30 +1197,47 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind)
Winbond. Determine the chip type now */ Winbond. Determine the chip type now */
if (kind <= 0) { if (kind <= 0) {
if (0x7b == w83793_read_value(client, W83793_REG_CHIPID)) { if (0x7b == i2c_smbus_read_byte_data(client,
W83793_REG_CHIPID)) {
kind = w83793; kind = w83793;
} else { } else {
if (kind == 0) if (kind == 0)
dev_warn(&adapter->dev, "w83793: Ignoring " dev_warn(&adapter->dev, "w83793: Ignoring "
"'force' parameter for unknown chip " "'force' parameter for unknown chip "
"at address 0x%02x\n", address); "at address 0x%02x\n", address);
err = -ENODEV; return -ENODEV;
goto free_mem;
} }
} }
/* Fill in the remaining client fields and put into the global list */ strlcpy(info->type, "w83793", I2C_NAME_SIZE);
strlcpy(client->name, "w83793", I2C_NAME_SIZE);
return 0;
}
static int w83793_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct w83793_data *data;
int i, tmp, val, err;
int files_fan = ARRAY_SIZE(w83793_left_fan) / 7;
int files_pwm = ARRAY_SIZE(w83793_left_pwm) / 5;
int files_temp = ARRAY_SIZE(w83793_temp) / 6;
data = kzalloc(sizeof(struct w83793_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
data->bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL);
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ err = w83793_detect_subclients(client);
if ((err = i2c_attach_client(client))) if (err)
goto free_mem; goto free_mem;
if ((err = w83793_detect_subclients(adapter, address, kind, client)))
goto detach_client;
/* Initialize the chip */ /* Initialize the chip */
w83793_init_client(client); w83793_init_client(client);
@ -1459,16 +1418,10 @@ exit_remove:
for (i = 0; i < ARRAY_SIZE(w83793_temp); i++) for (i = 0; i < ARRAY_SIZE(w83793_temp); i++)
device_remove_file(dev, &w83793_temp[i].dev_attr); device_remove_file(dev, &w83793_temp[i].dev_attr);
if (data->lm75[0] != NULL) { if (data->lm75[0] != NULL)
i2c_detach_client(data->lm75[0]); i2c_unregister_device(data->lm75[0]);
kfree(data->lm75[0]); if (data->lm75[1] != NULL)
} i2c_unregister_device(data->lm75[1]);
if (data->lm75[1] != NULL) {
i2c_detach_client(data->lm75[1]);
kfree(data->lm75[1]);
}
detach_client:
i2c_detach_client(client);
free_mem: free_mem:
kfree(data); kfree(data);
exit: exit:

View File

@ -81,10 +81,11 @@ I2C_CLIENT_INSMOD_1(w83l785ts);
* Functions declaration * Functions declaration
*/ */
static int w83l785ts_attach_adapter(struct i2c_adapter *adapter); static int w83l785ts_probe(struct i2c_client *client,
static int w83l785ts_detect(struct i2c_adapter *adapter, int address, const struct i2c_device_id *id);
int kind); static int w83l785ts_detect(struct i2c_client *client, int kind,
static int w83l785ts_detach_client(struct i2c_client *client); struct i2c_board_info *info);
static int w83l785ts_remove(struct i2c_client *client);
static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval); static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval);
static struct w83l785ts_data *w83l785ts_update_device(struct device *dev); static struct w83l785ts_data *w83l785ts_update_device(struct device *dev);
@ -92,12 +93,22 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev);
* Driver data (common to all clients) * Driver data (common to all clients)
*/ */
static const struct i2c_device_id w83l785ts_id[] = {
{ "w83l785ts", w83l785ts },
{ }
};
MODULE_DEVICE_TABLE(i2c, w83l785ts_id);
static struct i2c_driver w83l785ts_driver = { static struct i2c_driver w83l785ts_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "w83l785ts", .name = "w83l785ts",
}, },
.attach_adapter = w83l785ts_attach_adapter, .probe = w83l785ts_probe,
.detach_client = w83l785ts_detach_client, .remove = w83l785ts_remove,
.id_table = w83l785ts_id,
.detect = w83l785ts_detect,
.address_data = &addr_data,
}; };
/* /*
@ -105,7 +116,6 @@ static struct i2c_driver w83l785ts_driver = {
*/ */
struct w83l785ts_data { struct w83l785ts_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 */
@ -135,40 +145,14 @@ static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 1);
* Real code * Real code
*/ */
static int w83l785ts_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
static int w83l785ts_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, w83l785ts_detect);
}
/*
* The following function does more than just detection. If detection
* succeeds, it also registers the new chip.
*/
static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
struct w83l785ts_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 w83l785ts_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
/* The common I2C client data is placed right before the
* W83L785TS-specific data. */
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &w83l785ts_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
@ -188,8 +172,8 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
W83L785TS_REG_TYPE, 0) & 0xFC) != 0x00)) { W83L785TS_REG_TYPE, 0) & 0xFC) != 0x00)) {
dev_dbg(&adapter->dev, dev_dbg(&adapter->dev,
"W83L785TS-S detection failed at 0x%02x.\n", "W83L785TS-S detection failed at 0x%02x.\n",
address); new_client->addr);
goto exit_free; return -ENODEV;
} }
} }
@ -214,22 +198,34 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&adapter->dev, dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%04X, " "Unsupported chip (man_id=0x%04X, "
"chip_id=0x%02X).\n", man_id, chip_id); "chip_id=0x%02X).\n", man_id, chip_id);
goto exit_free; return -ENODEV;
} }
} }
/* We can fill in the remaining client fields. */ strlcpy(info->type, "w83l785ts", I2C_NAME_SIZE);
strlcpy(new_client->name, "w83l785ts", I2C_NAME_SIZE);
return 0;
}
static int w83l785ts_probe(struct i2c_client *new_client,
const struct i2c_device_id *id)
{
struct w83l785ts_data *data;
int err = 0;
data = kzalloc(sizeof(struct w83l785ts_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);
/* Default values in case the first read fails (unlikely). */ /* Default values in case the first read fails (unlikely). */
data->temp[1] = data->temp[0] = 0; data->temp[1] = data->temp[0] = 0;
/* Tell the I2C layer a new client has arrived. */
if ((err = i2c_attach_client(new_client)))
goto exit_free;
/* /*
* Initialize the W83L785TS chip * Initialize the W83L785TS chip
* Nothing yet, assume it is already started. * Nothing yet, assume it is already started.
@ -259,25 +255,20 @@ exit_remove:
&sensor_dev_attr_temp1_input.dev_attr); &sensor_dev_attr_temp1_input.dev_attr);
device_remove_file(&new_client->dev, device_remove_file(&new_client->dev,
&sensor_dev_attr_temp1_max.dev_attr); &sensor_dev_attr_temp1_max.dev_attr);
i2c_detach_client(new_client);
exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int w83l785ts_detach_client(struct i2c_client *client) static int w83l785ts_remove(struct i2c_client *client)
{ {
struct w83l785ts_data *data = i2c_get_clientdata(client); struct w83l785ts_data *data = i2c_get_clientdata(client);
int err;
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
device_remove_file(&client->dev, device_remove_file(&client->dev,
&sensor_dev_attr_temp1_input.dev_attr); &sensor_dev_attr_temp1_input.dev_attr);
device_remove_file(&client->dev, device_remove_file(&client->dev,
&sensor_dev_attr_temp1_max.dev_attr); &sensor_dev_attr_temp1_max.dev_attr);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;
@ -286,6 +277,18 @@ static int w83l785ts_detach_client(struct i2c_client *client)
static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval) static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval)
{ {
int value, i; int value, i;
struct device *dev;
const char *prefix;
/* We might be called during detection, at which point the client
isn't yet fully initialized, so we can't use dev_dbg on it */
if (i2c_get_clientdata(client)) {
dev = &client->dev;
prefix = "";
} else {
dev = &client->adapter->dev;
prefix = "w83l785ts: ";
}
/* Frequent read errors have been reported on Asus boards, so we /* Frequent read errors have been reported on Asus boards, so we
* retry on read errors. If it still fails (unlikely), return the * retry on read errors. If it still fails (unlikely), return the
@ -293,15 +296,15 @@ static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval)
for (i = 1; i <= MAX_RETRIES; i++) { for (i = 1; i <= MAX_RETRIES; i++) {
value = i2c_smbus_read_byte_data(client, reg); value = i2c_smbus_read_byte_data(client, reg);
if (value >= 0) { if (value >= 0) {
dev_dbg(&client->dev, "Read 0x%02x from register " dev_dbg(dev, "%sRead 0x%02x from register 0x%02x.\n",
"0x%02x.\n", value, reg); prefix, value, reg);
return value; return value;
} }
dev_dbg(&client->dev, "Read failed, will retry in %d.\n", i); dev_dbg(dev, "%sRead failed, will retry in %d.\n", prefix, i);
msleep(i); msleep(i);
} }
dev_err(&client->dev, "Couldn't read value from register 0x%02x.\n", dev_err(dev, "%sCouldn't read value from register 0x%02x.\n", prefix,
reg); reg);
return defval; return defval;
} }

View File

@ -121,7 +121,6 @@ DIV_TO_REG(long val)
} }
struct w83l786ng_data { struct w83l786ng_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 */
@ -146,18 +145,30 @@ struct w83l786ng_data {
u8 tolerance[2]; u8 tolerance[2];
}; };
static int w83l786ng_attach_adapter(struct i2c_adapter *adapter); static int w83l786ng_probe(struct i2c_client *client,
static int w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int w83l786ng_detach_client(struct i2c_client *client); static int w83l786ng_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static int w83l786ng_remove(struct i2c_client *client);
static void w83l786ng_init_client(struct i2c_client *client); static void w83l786ng_init_client(struct i2c_client *client);
static struct w83l786ng_data *w83l786ng_update_device(struct device *dev); static struct w83l786ng_data *w83l786ng_update_device(struct device *dev);
static const struct i2c_device_id w83l786ng_id[] = {
{ "w83l786ng", w83l786ng },
{ }
};
MODULE_DEVICE_TABLE(i2c, w83l786ng_id);
static struct i2c_driver w83l786ng_driver = { static struct i2c_driver w83l786ng_driver = {
.class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = "w83l786ng", .name = "w83l786ng",
}, },
.attach_adapter = w83l786ng_attach_adapter, .probe = w83l786ng_probe,
.detach_client = w83l786ng_detach_client, .remove = w83l786ng_remove,
.id_table = w83l786ng_id,
.detect = w83l786ng_detect,
.address_data = &addr_data,
}; };
static u8 static u8
@ -575,42 +586,15 @@ static const struct attribute_group w83l786ng_group = {
}; };
static int static int
w83l786ng_attach_adapter(struct i2c_adapter *adapter) w83l786ng_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, w83l786ng_detect);
}
static int
w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *client;
struct device *dev;
struct w83l786ng_data *data;
int i, err = 0;
u8 reg_tmp;
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 w83l786ng_{read,write}_value. */
if (!(data = kzalloc(sizeof(struct w83l786ng_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
dev = &client->dev;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &w83l786ng_driver;
/* /*
* Now we do the remaining detection. A negative kind means that * Now we do the remaining detection. A negative kind means that
* the driver was loaded with no force parameter (default), so we * the driver was loaded with no force parameter (default), so we
@ -627,8 +611,8 @@ w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind)
W83L786NG_REG_CONFIG) & 0x80) != 0x00)) { W83L786NG_REG_CONFIG) & 0x80) != 0x00)) {
dev_dbg(&adapter->dev, dev_dbg(&adapter->dev,
"W83L786NG detection failed at 0x%02x.\n", "W83L786NG detection failed at 0x%02x.\n",
address); client->addr);
goto exit_free; return -ENODEV;
} }
} }
@ -651,17 +635,31 @@ w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&adapter->dev, dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%04X, " "Unsupported chip (man_id=0x%04X, "
"chip_id=0x%02X).\n", man_id, chip_id); "chip_id=0x%02X).\n", man_id, chip_id);
goto exit_free; return -ENODEV;
} }
} }
/* Fill in the remaining client fields and put into the global list */ strlcpy(info->type, "w83l786ng", I2C_NAME_SIZE);
strlcpy(client->name, "w83l786ng", 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
w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct w83l786ng_data *data;
int i, err = 0;
u8 reg_tmp;
data = kzalloc(sizeof(struct w83l786ng_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
/* Initialize the chip */ /* Initialize the chip */
w83l786ng_init_client(client); w83l786ng_init_client(client);
@ -693,25 +691,19 @@ w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove: exit_remove:
sysfs_remove_group(&client->dev.kobj, &w83l786ng_group); sysfs_remove_group(&client->dev.kobj, &w83l786ng_group);
i2c_detach_client(client);
exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int static int
w83l786ng_detach_client(struct i2c_client *client) w83l786ng_remove(struct i2c_client *client)
{ {
struct w83l786ng_data *data = i2c_get_clientdata(client); struct w83l786ng_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, &w83l786ng_group); sysfs_remove_group(&client->dev.kobj, &w83l786ng_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(data); kfree(data);
return 0; return 0;

View File

@ -155,6 +155,16 @@ static int __init amd756_s4882_init(void)
int i, error; int i, error;
union i2c_smbus_data ioconfig; union i2c_smbus_data ioconfig;
/* Configure the PCA9556 multiplexer */
ioconfig.byte = 0x00; /* All I/O to output mode */
error = i2c_smbus_xfer(&amd756_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03,
I2C_SMBUS_BYTE_DATA, &ioconfig);
if (error) {
dev_err(&amd756_smbus.dev, "PCA9556 configuration failed\n");
error = -EIO;
goto ERROR0;
}
/* Unregister physical bus */ /* Unregister physical bus */
error = i2c_del_adapter(&amd756_smbus); error = i2c_del_adapter(&amd756_smbus);
if (error) { if (error) {
@ -198,22 +208,11 @@ static int __init amd756_s4882_init(void)
s4882_algo[3].smbus_xfer = amd756_access_virt3; s4882_algo[3].smbus_xfer = amd756_access_virt3;
s4882_algo[4].smbus_xfer = amd756_access_virt4; s4882_algo[4].smbus_xfer = amd756_access_virt4;
/* Configure the PCA9556 multiplexer */
ioconfig.byte = 0x00; /* All I/O to output mode */
error = amd756_smbus.algo->smbus_xfer(&amd756_smbus, 0x18, 0,
I2C_SMBUS_WRITE, 0x03,
I2C_SMBUS_BYTE_DATA, &ioconfig);
if (error) {
dev_err(&amd756_smbus.dev, "PCA9556 configuration failed\n");
error = -EIO;
goto ERROR3;
}
/* Register virtual adapters */ /* Register virtual adapters */
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
error = i2c_add_adapter(s4882_adapter+i); error = i2c_add_adapter(s4882_adapter+i);
if (error) { if (error) {
dev_err(&amd756_smbus.dev, printk(KERN_ERR "i2c-amd756-s4882: "
"Virtual adapter %d registration " "Virtual adapter %d registration "
"failed, module not inserted\n", i); "failed, module not inserted\n", i);
for (i--; i >= 0; i--) for (i--; i >= 0; i--)
@ -252,8 +251,8 @@ static void __exit amd756_s4882_exit(void)
/* Restore physical bus */ /* Restore physical bus */
if (i2c_add_adapter(&amd756_smbus)) if (i2c_add_adapter(&amd756_smbus))
dev_err(&amd756_smbus.dev, "Physical bus restoration " printk(KERN_ERR "i2c-amd756-s4882: "
"failed\n"); "Physical bus restoration failed\n");
} }
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");

View File

@ -150,6 +150,16 @@ static int __init nforce2_s4985_init(void)
int i, error; int i, error;
union i2c_smbus_data ioconfig; union i2c_smbus_data ioconfig;
/* Configure the PCA9556 multiplexer */
ioconfig.byte = 0x00; /* All I/O to output mode */
error = i2c_smbus_xfer(nforce2_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03,
I2C_SMBUS_BYTE_DATA, &ioconfig);
if (error) {
dev_err(&nforce2_smbus->dev, "PCA9556 configuration failed\n");
error = -EIO;
goto ERROR0;
}
/* Unregister physical bus */ /* Unregister physical bus */
if (!nforce2_smbus) if (!nforce2_smbus)
return -ENODEV; return -ENODEV;
@ -191,24 +201,13 @@ static int __init nforce2_s4985_init(void)
s4985_algo[3].smbus_xfer = nforce2_access_virt3; s4985_algo[3].smbus_xfer = nforce2_access_virt3;
s4985_algo[4].smbus_xfer = nforce2_access_virt4; s4985_algo[4].smbus_xfer = nforce2_access_virt4;
/* Configure the PCA9556 multiplexer */
ioconfig.byte = 0x00; /* All I/O to output mode */
error = nforce2_smbus->algo->smbus_xfer(nforce2_smbus, 0x18, 0,
I2C_SMBUS_WRITE, 0x03,
I2C_SMBUS_BYTE_DATA, &ioconfig);
if (error) {
dev_err(&nforce2_smbus->dev, "PCA9556 configuration failed\n");
error = -EIO;
goto ERROR3;
}
/* Register virtual adapters */ /* Register virtual adapters */
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
error = i2c_add_adapter(s4985_adapter + i); error = i2c_add_adapter(s4985_adapter + i);
if (error) { if (error) {
dev_err(&nforce2_smbus->dev, printk(KERN_ERR "i2c-nforce2-s4985: "
"Virtual adapter %d registration " "Virtual adapter %d registration "
"failed, module not inserted\n", i); "failed, module not inserted\n", i);
for (i--; i >= 0; i--) for (i--; i >= 0; i--)
i2c_del_adapter(s4985_adapter + i); i2c_del_adapter(s4985_adapter + i);
goto ERROR3; goto ERROR3;
@ -245,8 +244,8 @@ static void __exit nforce2_s4985_exit(void)
/* Restore physical bus */ /* Restore physical bus */
if (i2c_add_adapter(nforce2_smbus)) if (i2c_add_adapter(nforce2_smbus))
dev_err(&nforce2_smbus->dev, "Physical bus restoration " printk(KERN_ERR "i2c-nforce2-s4985: "
"failed\n"); "Physical bus restoration failed\n");
} }
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");

View File

@ -47,7 +47,6 @@ enum eeprom_nature {
/* Each client has this additional data */ /* Each client has this additional data */
struct eeprom_data { struct eeprom_data {
struct i2c_client client;
struct mutex update_lock; struct mutex update_lock;
u8 valid; /* bitfield, bit!=0 if slice is valid */ u8 valid; /* bitfield, bit!=0 if slice is valid */
unsigned long last_updated[8]; /* In jiffies, 8 slices */ unsigned long last_updated[8]; /* In jiffies, 8 slices */
@ -56,19 +55,6 @@ struct eeprom_data {
}; };
static int eeprom_attach_adapter(struct i2c_adapter *adapter);
static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind);
static int eeprom_detach_client(struct i2c_client *client);
/* This is the driver that will be inserted */
static struct i2c_driver eeprom_driver = {
.driver = {
.name = "eeprom",
},
.attach_adapter = eeprom_attach_adapter,
.detach_client = eeprom_detach_client,
};
static void eeprom_update_client(struct i2c_client *client, u8 slice) static void eeprom_update_client(struct i2c_client *client, u8 slice)
{ {
struct eeprom_data *data = i2c_get_clientdata(client); struct eeprom_data *data = i2c_get_clientdata(client);
@ -148,25 +134,17 @@ static struct bin_attribute eeprom_attr = {
.read = eeprom_read, .read = eeprom_read,
}; };
static int eeprom_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
static int eeprom_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
if (!(adapter->class & (I2C_CLASS_DDC | I2C_CLASS_SPD))) struct i2c_adapter *adapter = client->adapter;
return 0;
return i2c_probe(adapter, &addr_data, eeprom_detect);
}
/* This function is called by i2c_probe */
static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *client;
struct eeprom_data *data;
int err = 0;
/* EDID EEPROMs are often 24C00 EEPROMs, which answer to all /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all
addresses 0x50-0x57, but we only care about 0x50. So decline addresses 0x50-0x57, but we only care about 0x50. So decline
attaching to addresses >= 0x51 on DDC buses */ attaching to addresses >= 0x51 on DDC buses */
if (!(adapter->class & I2C_CLASS_SPD) && address >= 0x51) if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51)
goto exit; return -ENODEV;
/* There are four ways we can read the EEPROM data: /* There are four ways we can read the EEPROM data:
(1) I2C block reads (faster, but unsupported by most adapters) (1) I2C block reads (faster, but unsupported by most adapters)
@ -177,32 +155,33 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
because all known adapters support one of the first two. */ because all known adapters support one of the first two. */
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)
&& !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK))
goto exit; return -ENODEV;
strlcpy(info->type, "eeprom", I2C_NAME_SIZE);
return 0;
}
static int eeprom_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = client->adapter;
struct eeprom_data *data;
int err;
if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
err = -ENOMEM; err = -ENOMEM;
goto exit; goto exit;
} }
client = &data->client;
memset(data->data, 0xff, EEPROM_SIZE); memset(data->data, 0xff, EEPROM_SIZE);
i2c_set_clientdata(client, data); i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &eeprom_driver;
/* Fill in the remaining client fields */
strlcpy(client->name, "eeprom", I2C_NAME_SIZE);
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
data->nature = UNKNOWN; data->nature = UNKNOWN;
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(client)))
goto exit_kfree;
/* Detect the Vaio nature of EEPROMs. /* Detect the Vaio nature of EEPROMs.
We use the "PCG-" or "VGN-" prefix as the signature. */ We use the "PCG-" or "VGN-" prefix as the signature. */
if (address == 0x57 if (client->addr == 0x57
&& i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) { && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
char name[4]; char name[4];
@ -221,33 +200,42 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
/* create the sysfs eeprom file */ /* create the sysfs eeprom file */
err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr); err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr);
if (err) if (err)
goto exit_detach; goto exit_kfree;
return 0; return 0;
exit_detach:
i2c_detach_client(client);
exit_kfree: exit_kfree:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int eeprom_detach_client(struct i2c_client *client) static int eeprom_remove(struct i2c_client *client)
{ {
int err;
sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr);
err = i2c_detach_client(client);
if (err)
return err;
kfree(i2c_get_clientdata(client)); kfree(i2c_get_clientdata(client));
return 0; return 0;
} }
static const struct i2c_device_id eeprom_id[] = {
{ "eeprom", 0 },
{ }
};
static struct i2c_driver eeprom_driver = {
.driver = {
.name = "eeprom",
},
.probe = eeprom_probe,
.remove = eeprom_remove,
.id_table = eeprom_id,
.class = I2C_CLASS_DDC | I2C_CLASS_SPD,
.detect = eeprom_detect,
.address_data = &addr_data,
};
static int __init eeprom_init(void) static int __init eeprom_init(void)
{ {
return i2c_add_driver(&eeprom_driver); return i2c_add_driver(&eeprom_driver);

View File

@ -53,7 +53,7 @@ I2C_CLIENT_INSMOD_1(max6875);
/* Each client has this additional data */ /* Each client has this additional data */
struct max6875_data { struct max6875_data {
struct i2c_client client; struct i2c_client *fake_client;
struct mutex update_lock; struct mutex update_lock;
u32 valid; u32 valid;
@ -61,19 +61,6 @@ struct max6875_data {
unsigned long last_updated[USER_EEPROM_SLICES]; unsigned long last_updated[USER_EEPROM_SLICES];
}; };
static int max6875_attach_adapter(struct i2c_adapter *adapter);
static int max6875_detect(struct i2c_adapter *adapter, int address, int kind);
static int max6875_detach_client(struct i2c_client *client);
/* This is the driver that will be inserted */
static struct i2c_driver max6875_driver = {
.driver = {
.name = "max6875",
},
.attach_adapter = max6875_attach_adapter,
.detach_client = max6875_detach_client,
};
static void max6875_update_slice(struct i2c_client *client, int slice) static void max6875_update_slice(struct i2c_client *client, int slice)
{ {
struct max6875_data *data = i2c_get_clientdata(client); struct max6875_data *data = i2c_get_clientdata(client);
@ -159,96 +146,87 @@ static struct bin_attribute user_eeprom_attr = {
.read = max6875_read, .read = max6875_read,
}; };
static int max6875_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
static int max6875_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
return i2c_probe(adapter, &addr_data, max6875_detect); struct i2c_adapter *adapter = client->adapter;
}
/* This function is called by i2c_probe */
static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *real_client;
struct i2c_client *fake_client;
struct max6875_data *data;
int err;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
| I2C_FUNC_SMBUS_READ_BYTE)) | I2C_FUNC_SMBUS_READ_BYTE))
return 0; return -ENODEV;
/* Only check even addresses */ /* Only check even addresses */
if (address & 1) if (client->addr & 1)
return 0; return -ENODEV;
strlcpy(info->type, "max6875", I2C_NAME_SIZE);
return 0;
}
static int max6875_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct max6875_data *data;
int err;
if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL))) if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
/* A fake client is created on the odd address */ /* A fake client is created on the odd address */
if (!(fake_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { data->fake_client = i2c_new_dummy(client->adapter, client->addr + 1);
if (!data->fake_client) {
err = -ENOMEM; err = -ENOMEM;
goto exit_kfree1; goto exit_kfree;
} }
/* Init real i2c_client */ /* Init real i2c_client */
real_client = &data->client; i2c_set_clientdata(client, data);
i2c_set_clientdata(real_client, data);
real_client->addr = address;
real_client->adapter = adapter;
real_client->driver = &max6875_driver;
strlcpy(real_client->name, "max6875", I2C_NAME_SIZE);
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Init fake client data */ err = sysfs_create_bin_file(&client->dev.kobj, &user_eeprom_attr);
i2c_set_clientdata(fake_client, NULL);
fake_client->addr = address | 1;
fake_client->adapter = adapter;
fake_client->driver = &max6875_driver;
strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE);
if ((err = i2c_attach_client(real_client)) != 0)
goto exit_kfree2;
if ((err = i2c_attach_client(fake_client)) != 0)
goto exit_detach1;
err = sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
if (err) if (err)
goto exit_detach2; goto exit_remove_fake;
return 0; return 0;
exit_detach2: exit_remove_fake:
i2c_detach_client(fake_client); i2c_unregister_device(data->fake_client);
exit_detach1: exit_kfree:
i2c_detach_client(real_client);
exit_kfree2:
kfree(fake_client);
exit_kfree1:
kfree(data); kfree(data);
return err; return err;
} }
/* Will be called for both the real client and the fake client */ static int max6875_remove(struct i2c_client *client)
static int max6875_detach_client(struct i2c_client *client)
{ {
int err;
struct max6875_data *data = i2c_get_clientdata(client); struct max6875_data *data = i2c_get_clientdata(client);
/* data is NULL for the fake client */ i2c_unregister_device(data->fake_client);
if (data)
sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr);
err = i2c_detach_client(client); sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr);
if (err) kfree(data);
return err;
if (data) /* real client */
kfree(data);
else /* fake client */
kfree(client);
return 0; return 0;
} }
static const struct i2c_device_id max6875_id[] = {
{ "max6875", 0 },
{ }
};
static struct i2c_driver max6875_driver = {
.driver = {
.name = "max6875",
},
.probe = max6875_probe,
.remove = max6875_remove,
.id_table = max6875_id,
.detect = max6875_detect,
.address_data = &addr_data,
};
static int __init max6875_init(void) static int __init max6875_init(void)
{ {
return i2c_add_driver(&max6875_driver); return i2c_add_driver(&max6875_driver);

View File

@ -14,8 +14,8 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
/* Addresses to scan */ /* Addresses to scan: none, device is not autodetected */
static unsigned short normal_i2c[] = {0x74, 0x75, 0x76, 0x77, I2C_CLIENT_END}; static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
/* Insmod parameters */ /* Insmod parameters */
I2C_CLIENT_INSMOD_1(pca9539); I2C_CLIENT_INSMOD_1(pca9539);
@ -32,23 +32,6 @@ enum pca9539_cmd
PCA9539_DIRECTION_1 = 7, PCA9539_DIRECTION_1 = 7,
}; };
static int pca9539_attach_adapter(struct i2c_adapter *adapter);
static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind);
static int pca9539_detach_client(struct i2c_client *client);
/* This is the driver that will be inserted */
static struct i2c_driver pca9539_driver = {
.driver = {
.name = "pca9539",
},
.attach_adapter = pca9539_attach_adapter,
.detach_client = pca9539_detach_client,
};
struct pca9539_data {
struct i2c_client client;
};
/* following are the sysfs callback functions */ /* following are the sysfs callback functions */
static ssize_t pca9539_show(struct device *dev, struct device_attribute *attr, static ssize_t pca9539_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
@ -105,77 +88,51 @@ static struct attribute_group pca9539_defattr_group = {
.attrs = pca9539_attributes, .attrs = pca9539_attributes,
}; };
static int pca9539_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
static int pca9539_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
return i2c_probe(adapter, &addr_data, pca9539_detect); struct i2c_adapter *adapter = client->adapter;
}
/* This function is called by i2c_probe */
static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *client;
struct pca9539_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 strlcpy(info->type, "pca9539", I2C_NAME_SIZE);
client structure, even though we cannot fill it completely yet. */
if (!(data = kzalloc(sizeof(struct pca9539_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &pca9539_driver;
if (kind < 0) {
/* Detection: the pca9539 only has 8 registers (0-7).
A read of 7 should succeed, but a read of 8 should fail. */
if ((i2c_smbus_read_byte_data(client, 7) < 0) ||
(i2c_smbus_read_byte_data(client, 8) >= 0))
goto exit_kfree;
}
strlcpy(client->name, "pca9539", I2C_NAME_SIZE);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(client)))
goto exit_kfree;
/* Register sysfs hooks */
err = sysfs_create_group(&client->dev.kobj,
&pca9539_defattr_group);
if (err)
goto exit_detach;
return 0; return 0;
exit_detach:
i2c_detach_client(client);
exit_kfree:
kfree(data);
exit:
return err;
} }
static int pca9539_detach_client(struct i2c_client *client) static int pca9539_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{ {
int err; /* Register sysfs hooks */
return sysfs_create_group(&client->dev.kobj,
&pca9539_defattr_group);
}
static int pca9539_remove(struct i2c_client *client)
{
sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group); sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(i2c_get_clientdata(client));
return 0; return 0;
} }
static const struct i2c_device_id pca9539_id[] = {
{ "pca9539", 0 },
{ }
};
static struct i2c_driver pca9539_driver = {
.driver = {
.name = "pca9539",
},
.probe = pca9539_probe,
.remove = pca9539_remove,
.id_table = pca9539_id,
.detect = pca9539_detect,
.address_data = &addr_data,
};
static int __init pca9539_init(void) static int __init pca9539_init(void)
{ {
return i2c_add_driver(&pca9539_driver); return i2c_add_driver(&pca9539_driver);

View File

@ -38,37 +38,19 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
/* Addresses to scan */ /* Addresses to scan: none, device can't be detected */
static const unsigned short normal_i2c[] = { static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
I2C_CLIENT_END
};
/* Insmod parameters */ /* Insmod parameters */
I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a); I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a);
/* Each client has this additional data */ /* Each client has this additional data */
struct pcf8574_data { struct pcf8574_data {
struct i2c_client client;
int write; /* Remember last written value */ int write; /* Remember last written value */
}; };
static int pcf8574_attach_adapter(struct i2c_adapter *adapter);
static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind);
static int pcf8574_detach_client(struct i2c_client *client);
static void pcf8574_init_client(struct i2c_client *client); static void pcf8574_init_client(struct i2c_client *client);
/* This is the driver that will be inserted */
static struct i2c_driver pcf8574_driver = {
.driver = {
.name = "pcf8574",
},
.attach_adapter = pcf8574_attach_adapter,
.detach_client = pcf8574_detach_client,
};
/* following are the sysfs callback functions */ /* following are the sysfs callback functions */
static ssize_t show_read(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t show_read(struct device *dev, struct device_attribute *attr, char *buf)
{ {
@ -119,41 +101,22 @@ static const struct attribute_group pcf8574_attr_group = {
* Real code * Real code
*/ */
static int pcf8574_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
static int pcf8574_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
return i2c_probe(adapter, &addr_data, pcf8574_detect); struct i2c_adapter *adapter = client->adapter;
} const char *client_name;
/* This function is called by i2c_probe */
static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *client;
struct pcf8574_data *data;
int err = 0;
const char *client_name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_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. */
if (!(data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &pcf8574_driver;
/* Now, we would do the remaining detection. But the PCF8574 is plainly /* Now, we would do the remaining detection. But the PCF8574 is plainly
impossible to detect! Stupid chip. */ impossible to detect! Stupid chip. */
/* Determine the chip type */ /* Determine the chip type */
if (kind <= 0) { if (kind <= 0) {
if (address >= 0x38 && address <= 0x3f) if (client->addr >= 0x38 && client->addr <= 0x3f)
kind = pcf8574a; kind = pcf8574a;
else else
kind = pcf8574; kind = pcf8574;
@ -163,40 +126,43 @@ static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
client_name = "pcf8574a"; client_name = "pcf8574a";
else else
client_name = "pcf8574"; client_name = "pcf8574";
strlcpy(info->type, client_name, I2C_NAME_SIZE);
/* Fill in the remaining client fields and put it into the global list */ return 0;
strlcpy(client->name, client_name, I2C_NAME_SIZE); }
static int pcf8574_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pcf8574_data *data;
int err;
data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(client)))
goto exit_free;
/* Initialize the PCF8574 chip */ /* Initialize the PCF8574 chip */
pcf8574_init_client(client); pcf8574_init_client(client);
/* Register sysfs hooks */ /* Register sysfs hooks */
err = sysfs_create_group(&client->dev.kobj, &pcf8574_attr_group); err = sysfs_create_group(&client->dev.kobj, &pcf8574_attr_group);
if (err) if (err)
goto exit_detach; goto exit_free;
return 0; return 0;
exit_detach:
i2c_detach_client(client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int pcf8574_detach_client(struct i2c_client *client) static int pcf8574_remove(struct i2c_client *client)
{ {
int err;
sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group); sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(i2c_get_clientdata(client)); kfree(i2c_get_clientdata(client));
return 0; return 0;
} }
@ -208,6 +174,24 @@ static void pcf8574_init_client(struct i2c_client *client)
data->write = -EAGAIN; data->write = -EAGAIN;
} }
static const struct i2c_device_id pcf8574_id[] = {
{ "pcf8574", 0 },
{ "pcf8574a", 0 },
{ }
};
static struct i2c_driver pcf8574_driver = {
.driver = {
.name = "pcf8574",
},
.probe = pcf8574_probe,
.remove = pcf8574_remove,
.id_table = pcf8574_id,
.detect = pcf8574_detect,
.address_data = &addr_data,
};
static int __init pcf8574_init(void) static int __init pcf8574_init(void)
{ {
return i2c_add_driver(&pcf8574_driver); return i2c_add_driver(&pcf8574_driver);

View File

@ -32,11 +32,8 @@
#include <linux/slab.h> /* kzalloc() */ #include <linux/slab.h> /* kzalloc() */
#include <linux/sysfs.h> /* sysfs_create_group() */ #include <linux/sysfs.h> /* sysfs_create_group() */
/* Addresses to scan */ /* Addresses to scan: none, device can't be detected */
static const unsigned short normal_i2c[] = { static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
I2C_CLIENT_END
};
/* Insmod parameters */ /* Insmod parameters */
I2C_CLIENT_INSMOD; I2C_CLIENT_INSMOD;
@ -44,24 +41,9 @@ I2C_CLIENT_INSMOD;
/* Each client has this additional data */ /* Each client has this additional data */
struct pcf8575_data { struct pcf8575_data {
struct i2c_client client;
int write; /* last written value, or error code */ int write; /* last written value, or error code */
}; };
static int pcf8575_attach_adapter(struct i2c_adapter *adapter);
static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind);
static int pcf8575_detach_client(struct i2c_client *client);
/* This is the driver that will be inserted */
static struct i2c_driver pcf8575_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "pcf8575",
},
.attach_adapter = pcf8575_attach_adapter,
.detach_client = pcf8575_detach_client,
};
/* following are the sysfs callback functions */ /* following are the sysfs callback functions */
static ssize_t show_read(struct device *dev, struct device_attribute *attr, static ssize_t show_read(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
@ -126,75 +108,77 @@ static const struct attribute_group pcf8575_attr_group = {
* Real code * Real code
*/ */
static int pcf8575_attach_adapter(struct i2c_adapter *adapter) /* Return 0 if detection is successful, -ENODEV otherwise */
static int pcf8575_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
return i2c_probe(adapter, &addr_data, pcf8575_detect); struct i2c_adapter *adapter = client->adapter;
}
/* This function is called by i2c_probe */
static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *client;
struct pcf8575_data *data;
int err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
goto exit; return -ENODEV;
/* This is the place to detect whether the chip at the specified
address really is a PCF8575 chip. However, there is no method known
to detect whether an I2C chip is a PCF8575 or any other I2C chip. */
strlcpy(info->type, "pcf8575", I2C_NAME_SIZE);
return 0;
}
static int pcf8575_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pcf8575_data *data;
int err;
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet. */
data = kzalloc(sizeof(struct pcf8575_data), GFP_KERNEL); data = kzalloc(sizeof(struct pcf8575_data), GFP_KERNEL);
if (!data) { if (!data) {
err = -ENOMEM; err = -ENOMEM;
goto exit; goto exit;
} }
client = &data->client;
i2c_set_clientdata(client, data); i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &pcf8575_driver;
strlcpy(client->name, "pcf8575", I2C_NAME_SIZE);
data->write = -EAGAIN; data->write = -EAGAIN;
/* This is the place to detect whether the chip at the specified
address really is a PCF8575 chip. However, there is no method known
to detect whether an I2C chip is a PCF8575 or any other I2C chip. */
/* 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, &pcf8575_attr_group); err = sysfs_create_group(&client->dev.kobj, &pcf8575_attr_group);
if (err) if (err)
goto exit_detach; goto exit_free;
return 0; return 0;
exit_detach:
i2c_detach_client(client);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int pcf8575_detach_client(struct i2c_client *client) static int pcf8575_remove(struct i2c_client *client)
{ {
int err;
sysfs_remove_group(&client->dev.kobj, &pcf8575_attr_group); sysfs_remove_group(&client->dev.kobj, &pcf8575_attr_group);
err = i2c_detach_client(client);
if (err)
return err;
kfree(i2c_get_clientdata(client)); kfree(i2c_get_clientdata(client));
return 0; return 0;
} }
static const struct i2c_device_id pcf8575_id[] = {
{ "pcf8575", 0 },
{ }
};
static struct i2c_driver pcf8575_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "pcf8575",
},
.probe = pcf8575_probe,
.remove = pcf8575_remove,
.id_table = pcf8575_id,
.detect = pcf8575_detect,
.address_data = &addr_data,
};
static int __init pcf8575_init(void) static int __init pcf8575_init(void)
{ {
return i2c_add_driver(&pcf8575_driver); return i2c_add_driver(&pcf8575_driver);

View File

@ -72,28 +72,15 @@ MODULE_PARM_DESC(input_mode,
#define REG_TO_SIGNED(reg) (((reg) & 0x80)?((reg) - 256):(reg)) #define REG_TO_SIGNED(reg) (((reg) & 0x80)?((reg) - 256):(reg))
struct pcf8591_data { struct pcf8591_data {
struct i2c_client client;
struct mutex update_lock; struct mutex update_lock;
u8 control; u8 control;
u8 aout; u8 aout;
}; };
static int pcf8591_attach_adapter(struct i2c_adapter *adapter);
static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind);
static int pcf8591_detach_client(struct i2c_client *client);
static void pcf8591_init_client(struct i2c_client *client); static void pcf8591_init_client(struct i2c_client *client);
static int pcf8591_read_channel(struct device *dev, int channel); static int pcf8591_read_channel(struct device *dev, int channel);
/* This is the driver that will be inserted */
static struct i2c_driver pcf8591_driver = {
.driver = {
.name = "pcf8591",
},
.attach_adapter = pcf8591_attach_adapter,
.detach_client = pcf8591_detach_client,
};
/* following are the sysfs callback functions */ /* following are the sysfs callback functions */
#define show_in_channel(channel) \ #define show_in_channel(channel) \
static ssize_t show_in##channel##_input(struct device *dev, struct device_attribute *attr, char *buf) \ static ssize_t show_in##channel##_input(struct device *dev, struct device_attribute *attr, char *buf) \
@ -180,58 +167,46 @@ static const struct attribute_group pcf8591_attr_group_opt = {
/* /*
* Real code * Real code
*/ */
static int pcf8591_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_probe(adapter, &addr_data, pcf8591_detect);
}
/* This function is called by i2c_probe */ /* Return 0 if detection is successful, -ENODEV otherwise */
static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) static int pcf8591_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{ {
struct i2c_client *client; struct i2c_adapter *adapter = client->adapter;
struct pcf8591_data *data;
int err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE
| I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
goto exit; return -ENODEV;
/* Now, we would do the remaining detection. But the PCF8591 is plainly
impossible to detect! Stupid chip. */
strlcpy(info->type, "pcf8591", I2C_NAME_SIZE);
return 0;
}
static int pcf8591_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pcf8591_data *data;
int err;
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet. */
if (!(data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) { if (!(data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) {
err = -ENOMEM; err = -ENOMEM;
goto exit; goto exit;
} }
client = &data->client;
i2c_set_clientdata(client, data); i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &pcf8591_driver;
/* Now, we would do the remaining detection. But the PCF8591 is plainly
impossible to detect! Stupid chip. */
/* Determine the chip type - only one kind supported! */
if (kind <= 0)
kind = pcf8591;
/* Fill in the remaining client fields and put it into the global
list */
strlcpy(client->name, "pcf8591", 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_kfree;
/* Initialize the PCF8591 chip */ /* Initialize the PCF8591 chip */
pcf8591_init_client(client); pcf8591_init_client(client);
/* Register sysfs hooks */ /* Register sysfs hooks */
err = sysfs_create_group(&client->dev.kobj, &pcf8591_attr_group); err = sysfs_create_group(&client->dev.kobj, &pcf8591_attr_group);
if (err) if (err)
goto exit_detach; goto exit_kfree;
/* Register input2 if not in "two differential inputs" mode */ /* Register input2 if not in "two differential inputs" mode */
if (input_mode != 3) { if (input_mode != 3) {
@ -252,24 +227,16 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
exit_sysfs_remove: exit_sysfs_remove:
sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);
exit_detach:
i2c_detach_client(client);
exit_kfree: exit_kfree:
kfree(data); kfree(data);
exit: exit:
return err; return err;
} }
static int pcf8591_detach_client(struct i2c_client *client) static int pcf8591_remove(struct i2c_client *client)
{ {
int err;
sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(i2c_get_clientdata(client)); kfree(i2c_get_clientdata(client));
return 0; return 0;
} }
@ -316,6 +283,25 @@ static int pcf8591_read_channel(struct device *dev, int channel)
return (10 * value); return (10 * value);
} }
static const struct i2c_device_id pcf8591_id[] = {
{ "pcf8591", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcf8591_id);
static struct i2c_driver pcf8591_driver = {
.driver = {
.name = "pcf8591",
},
.probe = pcf8591_probe,
.remove = pcf8591_remove,
.id_table = pcf8591_id,
.class = I2C_CLASS_HWMON, /* Nearest choice */
.detect = pcf8591_detect,
.address_data = &addr_data,
};
static int __init pcf8591_init(void) static int __init pcf8591_init(void)
{ {
if (input_mode < 0 || input_mode > 3) { if (input_mode < 0 || input_mode > 3) {

View File

@ -654,6 +654,10 @@ int i2c_del_adapter(struct i2c_adapter *adap)
dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
/* Clear the device structure in case this adapter is ever going to be
added again */
memset(&adap->dev, 0, sizeof(adap->dev));
out_unlock: out_unlock:
mutex_unlock(&core_lock); mutex_unlock(&core_lock);
return res; return res;

View File

@ -94,21 +94,31 @@ static const u8 ds2482_chan_rd[8] =
#define DS2482_REG_STS_1WB 0x01 #define DS2482_REG_STS_1WB 0x01
static int ds2482_attach_adapter(struct i2c_adapter *adapter); static int ds2482_probe(struct i2c_client *client,
static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind); const struct i2c_device_id *id);
static int ds2482_detach_client(struct i2c_client *client); static int ds2482_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info);
static int ds2482_remove(struct i2c_client *client);
/** /**
* Driver data (common to all clients) * Driver data (common to all clients)
*/ */
static const struct i2c_device_id ds2482_id[] = {
{ "ds2482", 0 },
{ }
};
static struct i2c_driver ds2482_driver = { static struct i2c_driver ds2482_driver = {
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "ds2482", .name = "ds2482",
}, },
.attach_adapter = ds2482_attach_adapter, .probe = ds2482_probe,
.detach_client = ds2482_detach_client, .remove = ds2482_remove,
.id_table = ds2482_id,
.detect = ds2482_detect,
.address_data = &addr_data,
}; };
/* /*
@ -124,7 +134,7 @@ struct ds2482_w1_chan {
}; };
struct ds2482_data { struct ds2482_data {
struct i2c_client client; struct i2c_client *client;
struct mutex access_lock; struct mutex access_lock;
/* 1-wire interface(s) */ /* 1-wire interface(s) */
@ -147,7 +157,7 @@ struct ds2482_data {
static inline int ds2482_select_register(struct ds2482_data *pdev, u8 read_ptr) static inline int ds2482_select_register(struct ds2482_data *pdev, u8 read_ptr)
{ {
if (pdev->read_prt != read_ptr) { if (pdev->read_prt != read_ptr) {
if (i2c_smbus_write_byte_data(&pdev->client, if (i2c_smbus_write_byte_data(pdev->client,
DS2482_CMD_SET_READ_PTR, DS2482_CMD_SET_READ_PTR,
read_ptr) < 0) read_ptr) < 0)
return -1; return -1;
@ -167,7 +177,7 @@ static inline int ds2482_select_register(struct ds2482_data *pdev, u8 read_ptr)
*/ */
static inline int ds2482_send_cmd(struct ds2482_data *pdev, u8 cmd) static inline int ds2482_send_cmd(struct ds2482_data *pdev, u8 cmd)
{ {
if (i2c_smbus_write_byte(&pdev->client, cmd) < 0) if (i2c_smbus_write_byte(pdev->client, cmd) < 0)
return -1; return -1;
pdev->read_prt = DS2482_PTR_CODE_STATUS; pdev->read_prt = DS2482_PTR_CODE_STATUS;
@ -187,7 +197,7 @@ static inline int ds2482_send_cmd(struct ds2482_data *pdev, u8 cmd)
static inline int ds2482_send_cmd_data(struct ds2482_data *pdev, static inline int ds2482_send_cmd_data(struct ds2482_data *pdev,
u8 cmd, u8 byte) u8 cmd, u8 byte)
{ {
if (i2c_smbus_write_byte_data(&pdev->client, cmd, byte) < 0) if (i2c_smbus_write_byte_data(pdev->client, cmd, byte) < 0)
return -1; return -1;
/* all cmds leave in STATUS, except CONFIG */ /* all cmds leave in STATUS, except CONFIG */
@ -216,7 +226,7 @@ static int ds2482_wait_1wire_idle(struct ds2482_data *pdev)
if (!ds2482_select_register(pdev, DS2482_PTR_CODE_STATUS)) { if (!ds2482_select_register(pdev, DS2482_PTR_CODE_STATUS)) {
do { do {
temp = i2c_smbus_read_byte(&pdev->client); temp = i2c_smbus_read_byte(pdev->client);
} while ((temp >= 0) && (temp & DS2482_REG_STS_1WB) && } while ((temp >= 0) && (temp & DS2482_REG_STS_1WB) &&
(++retries < DS2482_WAIT_IDLE_TIMEOUT)); (++retries < DS2482_WAIT_IDLE_TIMEOUT));
} }
@ -238,13 +248,13 @@ static int ds2482_wait_1wire_idle(struct ds2482_data *pdev)
*/ */
static int ds2482_set_channel(struct ds2482_data *pdev, u8 channel) static int ds2482_set_channel(struct ds2482_data *pdev, u8 channel)
{ {
if (i2c_smbus_write_byte_data(&pdev->client, DS2482_CMD_CHANNEL_SELECT, if (i2c_smbus_write_byte_data(pdev->client, DS2482_CMD_CHANNEL_SELECT,
ds2482_chan_wr[channel]) < 0) ds2482_chan_wr[channel]) < 0)
return -1; return -1;
pdev->read_prt = DS2482_PTR_CODE_CHANNEL; pdev->read_prt = DS2482_PTR_CODE_CHANNEL;
pdev->channel = -1; pdev->channel = -1;
if (i2c_smbus_read_byte(&pdev->client) == ds2482_chan_rd[channel]) { if (i2c_smbus_read_byte(pdev->client) == ds2482_chan_rd[channel]) {
pdev->channel = channel; pdev->channel = channel;
return 0; return 0;
} }
@ -368,7 +378,7 @@ static u8 ds2482_w1_read_byte(void *data)
ds2482_select_register(pdev, DS2482_PTR_CODE_DATA); ds2482_select_register(pdev, DS2482_PTR_CODE_DATA);
/* Read the data byte */ /* Read the data byte */
result = i2c_smbus_read_byte(&pdev->client); result = i2c_smbus_read_byte(pdev->client);
mutex_unlock(&pdev->access_lock); mutex_unlock(&pdev->access_lock);
@ -415,47 +425,38 @@ static u8 ds2482_w1_reset_bus(void *data)
} }
/** static int ds2482_detect(struct i2c_client *client, int kind,
* Called to see if the device exists on an i2c bus. struct i2c_board_info *info)
*/
static int ds2482_attach_adapter(struct i2c_adapter *adapter)
{ {
return i2c_probe(adapter, &addr_data, ds2482_detect); if (!i2c_check_functionality(client->adapter,
}
/*
* The following function does more than just detection. If detection
* succeeds, it also registers the new chip.
*/
static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct ds2482_data *data;
struct i2c_client *new_client;
int err = 0;
int temp1;
int idx;
if (!i2c_check_functionality(adapter,
I2C_FUNC_SMBUS_WRITE_BYTE_DATA | I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
I2C_FUNC_SMBUS_BYTE)) I2C_FUNC_SMBUS_BYTE))
goto exit; return -ENODEV;
strlcpy(info->type, "ds2482", I2C_NAME_SIZE);
return 0;
}
static int ds2482_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct ds2482_data *data;
int err = -ENODEV;
int temp1;
int idx;
if (!(data = kzalloc(sizeof(struct ds2482_data), GFP_KERNEL))) { if (!(data = kzalloc(sizeof(struct ds2482_data), GFP_KERNEL))) {
err = -ENOMEM; err = -ENOMEM;
goto exit; goto exit;
} }
new_client = &data->client; data->client = client;
i2c_set_clientdata(new_client, data); i2c_set_clientdata(client, data);
new_client->addr = address;
new_client->driver = &ds2482_driver;
new_client->adapter = adapter;
/* Reset the device (sets the read_ptr to status) */ /* Reset the device (sets the read_ptr to status) */
if (ds2482_send_cmd(data, DS2482_CMD_RESET) < 0) { if (ds2482_send_cmd(data, DS2482_CMD_RESET) < 0) {
dev_dbg(&adapter->dev, "DS2482 reset failed at 0x%02x.\n", dev_warn(&client->dev, "DS2482 reset failed.\n");
address);
goto exit_free; goto exit_free;
} }
@ -463,10 +464,10 @@ static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind)
ndelay(525); ndelay(525);
/* Read the status byte - only reset bit and line should be set */ /* Read the status byte - only reset bit and line should be set */
temp1 = i2c_smbus_read_byte(new_client); temp1 = i2c_smbus_read_byte(client);
if (temp1 != (DS2482_REG_STS_LL | DS2482_REG_STS_RST)) { if (temp1 != (DS2482_REG_STS_LL | DS2482_REG_STS_RST)) {
dev_dbg(&adapter->dev, "DS2482 (0x%02x) reset status " dev_warn(&client->dev, "DS2482 reset status "
"0x%02X - not a DS2482\n", address, temp1); "0x%02X - not a DS2482\n", temp1);
goto exit_free; goto exit_free;
} }
@ -478,16 +479,8 @@ static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind)
/* Set all config items to 0 (off) */ /* Set all config items to 0 (off) */
ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG, 0xF0); ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG, 0xF0);
/* We can fill in the remaining client fields */
snprintf(new_client->name, sizeof(new_client->name), "ds2482-%d00",
data->w1_count);
mutex_init(&data->access_lock); mutex_init(&data->access_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_free;
/* Register 1-wire interface(s) */ /* Register 1-wire interface(s) */
for (idx = 0; idx < data->w1_count; idx++) { for (idx = 0; idx < data->w1_count; idx++) {
data->w1_ch[idx].pdev = data; data->w1_ch[idx].pdev = data;
@ -511,8 +504,6 @@ static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind)
return 0; return 0;
exit_w1_remove: exit_w1_remove:
i2c_detach_client(new_client);
for (idx = 0; idx < data->w1_count; idx++) { for (idx = 0; idx < data->w1_count; idx++) {
if (data->w1_ch[idx].pdev != NULL) if (data->w1_ch[idx].pdev != NULL)
w1_remove_master_device(&data->w1_ch[idx].w1_bm); w1_remove_master_device(&data->w1_ch[idx].w1_bm);
@ -523,10 +514,10 @@ exit:
return err; return err;
} }
static int ds2482_detach_client(struct i2c_client *client) static int ds2482_remove(struct i2c_client *client)
{ {
struct ds2482_data *data = i2c_get_clientdata(client); struct ds2482_data *data = i2c_get_clientdata(client);
int err, idx; int idx;
/* Unregister the 1-wire bridge(s) */ /* Unregister the 1-wire bridge(s) */
for (idx = 0; idx < data->w1_count; idx++) { for (idx = 0; idx < data->w1_count; idx++) {
@ -534,13 +525,6 @@ static int ds2482_detach_client(struct i2c_client *client)
w1_remove_master_device(&data->w1_ch[idx].w1_bm); w1_remove_master_device(&data->w1_ch[idx].w1_bm);
} }
/* Detach the i2c device */
if ((err = i2c_detach_client(client))) {
dev_err(&client->dev,
"Deregistration failed, client not detached.\n");
return err;
}
/* Free the memory */ /* Free the memory */
kfree(data); kfree(data);
return 0; return 0;