X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fi2c%2Fchips%2Fpcf8591.c;h=4dc36376eb3267f5b702b33ccdc80f0a5a7d926d;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=b6b927d8b372627a9bfdae20c8d0c2ebaa65bf8a;hpb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;p=linux-2.6.git diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c index b6b927d8b..4dc36376e 100644 --- a/drivers/i2c/chips/pcf8591.c +++ b/drivers/i2c/chips/pcf8591.c @@ -24,15 +24,14 @@ #include #include #include -#include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; -static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ -SENSORS_INSMOD_1(pcf8591); +I2C_CLIENT_INSMOD_1(pcf8591); static int input_mode; module_param(input_mode, int, 0); @@ -76,7 +75,7 @@ MODULE_PARM_DESC(input_mode, struct pcf8591_data { struct i2c_client client; - struct semaphore update_lock; + struct mutex update_lock; u8 control; u8 aout; @@ -90,17 +89,17 @@ static int pcf8591_read_channel(struct device *dev, int channel); /* This is the driver that will be inserted */ static struct i2c_driver pcf8591_driver = { - .owner = THIS_MODULE, - .name = "pcf8591", + .driver = { + .name = "pcf8591", + }, .id = I2C_DRIVERID_PCF8591, - .flags = I2C_DF_NOTIFY, .attach_adapter = pcf8591_attach_adapter, .detach_client = pcf8591_detach_client, }; /* following are the sysfs callback functions */ #define show_in_channel(channel) \ -static ssize_t show_in##channel##_input(struct device *dev, char *buf) \ +static ssize_t show_in##channel##_input(struct device *dev, struct device_attribute *attr, char *buf) \ { \ return sprintf(buf, "%d\n", pcf8591_read_channel(dev, channel));\ } \ @@ -112,13 +111,13 @@ show_in_channel(1); show_in_channel(2); show_in_channel(3); -static ssize_t show_out0_ouput(struct device *dev, char *buf) +static ssize_t show_out0_ouput(struct device *dev, struct device_attribute *attr, char *buf) { struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev)); return sprintf(buf, "%d\n", data->aout * 10); } -static ssize_t set_out0_output(struct device *dev, const char *buf, size_t count) +static ssize_t set_out0_output(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned int value; struct i2c_client *client = to_i2c_client(dev); @@ -134,41 +133,63 @@ static ssize_t set_out0_output(struct device *dev, const char *buf, size_t count static DEVICE_ATTR(out0_output, S_IWUSR | S_IRUGO, show_out0_ouput, set_out0_output); -static ssize_t show_out0_enable(struct device *dev, char *buf) +static ssize_t show_out0_enable(struct device *dev, struct device_attribute *attr, char *buf) { struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev)); return sprintf(buf, "%u\n", !(!(data->control & PCF8591_CONTROL_AOEF))); } -static ssize_t set_out0_enable(struct device *dev, const char *buf, size_t count) +static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct pcf8591_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (val) data->control |= PCF8591_CONTROL_AOEF; else data->control &= ~PCF8591_CONTROL_AOEF; i2c_smbus_write_byte(client, data->control); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO, show_out0_enable, set_out0_enable); +static struct attribute *pcf8591_attributes[] = { + &dev_attr_out0_enable.attr, + &dev_attr_out0_output.attr, + &dev_attr_in0_input.attr, + &dev_attr_in1_input.attr, + NULL +}; + +static const struct attribute_group pcf8591_attr_group = { + .attrs = pcf8591_attributes, +}; + +static struct attribute *pcf8591_attributes_opt[] = { + &dev_attr_in2_input.attr, + &dev_attr_in3_input.attr, + NULL +}; + +static const struct attribute_group pcf8591_attr_group_opt = { + .attrs = pcf8591_attributes_opt, +}; + /* * Real code */ static int pcf8591_attach_adapter(struct i2c_adapter *adapter) { - return i2c_detect(adapter, &addr_data, pcf8591_detect); + return i2c_probe(adapter, &addr_data, pcf8591_detect); } -/* This function is called by i2c_detect */ -int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) +/* This function is called by i2c_probe */ +static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) { struct i2c_client *new_client; struct pcf8591_data *data; @@ -180,11 +201,10 @@ int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) /* 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 = kmalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) { + if (!(data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) { err = -ENOMEM; goto exit; } - memset(data, 0, sizeof(struct pcf8591_data)); new_client = &data->client; i2c_set_clientdata(new_client, data); @@ -203,7 +223,7 @@ int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields and put it into the global list */ strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE); - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -213,24 +233,31 @@ int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) pcf8591_init_client(new_client); /* Register sysfs hooks */ - device_create_file(&new_client->dev, &dev_attr_out0_enable); - device_create_file(&new_client->dev, &dev_attr_out0_output); - device_create_file(&new_client->dev, &dev_attr_in0_input); - device_create_file(&new_client->dev, &dev_attr_in1_input); + err = sysfs_create_group(&new_client->dev.kobj, &pcf8591_attr_group); + if (err) + goto exit_detach; /* Register input2 if not in "two differential inputs" mode */ - if (input_mode != 3 ) - device_create_file(&new_client->dev, &dev_attr_in2_input); - + if (input_mode != 3) { + if ((err = device_create_file(&new_client->dev, + &dev_attr_in2_input))) + goto exit_sysfs_remove; + } + /* Register input3 only in "four single ended inputs" mode */ - if (input_mode == 0) - device_create_file(&new_client->dev, &dev_attr_in3_input); - + if (input_mode == 0) { + if ((err = device_create_file(&new_client->dev, + &dev_attr_in3_input))) + goto exit_sysfs_remove; + } + return 0; - - /* OK, this is not exactly good programming practice, usually. But it is - very code-efficient in this case. */ +exit_sysfs_remove: + sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group_opt); + sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group); +exit_detach: + i2c_detach_client(new_client); exit_kfree: kfree(data); exit: @@ -241,11 +268,11 @@ static int pcf8591_detach_client(struct i2c_client *client) { int err; - if ((err = i2c_detach_client(client))) { - dev_err(&client->dev, - "Client deregistration failed, client not detached.\n"); + sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); + sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); + + if ((err = i2c_detach_client(client))) return err; - } kfree(i2c_get_clientdata(client)); return 0; @@ -271,7 +298,7 @@ static int pcf8591_read_channel(struct device *dev, int channel) struct i2c_client *client = to_i2c_client(dev); struct pcf8591_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel) { data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK) @@ -284,7 +311,7 @@ static int pcf8591_read_channel(struct device *dev, int channel) } value = i2c_smbus_read_byte(client); - up(&data->update_lock); + mutex_unlock(&data->update_lock); if ((channel == 2 && input_mode == 2) || (channel != 3 && (input_mode == 1 || input_mode == 3)))