aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/chips/pcf8591.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/chips/pcf8591.c')
-rw-r--r--drivers/i2c/chips/pcf8591.c58
1 files changed, 45 insertions, 13 deletions
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index 925a6b371fd2..4dc36376eb32 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -158,6 +158,28 @@ static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr
158static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO, 158static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO,
159 show_out0_enable, set_out0_enable); 159 show_out0_enable, set_out0_enable);
160 160
161static struct attribute *pcf8591_attributes[] = {
162 &dev_attr_out0_enable.attr,
163 &dev_attr_out0_output.attr,
164 &dev_attr_in0_input.attr,
165 &dev_attr_in1_input.attr,
166 NULL
167};
168
169static const struct attribute_group pcf8591_attr_group = {
170 .attrs = pcf8591_attributes,
171};
172
173static struct attribute *pcf8591_attributes_opt[] = {
174 &dev_attr_in2_input.attr,
175 &dev_attr_in3_input.attr,
176 NULL
177};
178
179static const struct attribute_group pcf8591_attr_group_opt = {
180 .attrs = pcf8591_attributes_opt,
181};
182
161/* 183/*
162 * Real code 184 * Real code
163 */ 185 */
@@ -211,24 +233,31 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
211 pcf8591_init_client(new_client); 233 pcf8591_init_client(new_client);
212 234
213 /* Register sysfs hooks */ 235 /* Register sysfs hooks */
214 device_create_file(&new_client->dev, &dev_attr_out0_enable); 236 err = sysfs_create_group(&new_client->dev.kobj, &pcf8591_attr_group);
215 device_create_file(&new_client->dev, &dev_attr_out0_output); 237 if (err)
216 device_create_file(&new_client->dev, &dev_attr_in0_input); 238 goto exit_detach;
217 device_create_file(&new_client->dev, &dev_attr_in1_input);
218 239
219 /* Register input2 if not in "two differential inputs" mode */ 240 /* Register input2 if not in "two differential inputs" mode */
220 if (input_mode != 3 ) 241 if (input_mode != 3) {
221 device_create_file(&new_client->dev, &dev_attr_in2_input); 242 if ((err = device_create_file(&new_client->dev,
222 243 &dev_attr_in2_input)))
244 goto exit_sysfs_remove;
245 }
246
223 /* Register input3 only in "four single ended inputs" mode */ 247 /* Register input3 only in "four single ended inputs" mode */
224 if (input_mode == 0) 248 if (input_mode == 0) {
225 device_create_file(&new_client->dev, &dev_attr_in3_input); 249 if ((err = device_create_file(&new_client->dev,
226 250 &dev_attr_in3_input)))
251 goto exit_sysfs_remove;
252 }
253
227 return 0; 254 return 0;
228
229 /* OK, this is not exactly good programming practice, usually. But it is
230 very code-efficient in this case. */
231 255
256exit_sysfs_remove:
257 sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group_opt);
258 sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group);
259exit_detach:
260 i2c_detach_client(new_client);
232exit_kfree: 261exit_kfree:
233 kfree(data); 262 kfree(data);
234exit: 263exit:
@@ -239,6 +268,9 @@ static int pcf8591_detach_client(struct i2c_client *client)
239{ 268{
240 int err; 269 int err;
241 270
271 sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
272 sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);
273
242 if ((err = i2c_detach_client(client))) 274 if ((err = i2c_detach_client(client)))
243 return err; 275 return err;
244 276