On Tue, Nov 06, 2007 at 02:33:53AM -0800, akpm@linux-foundation.org wrote:
[mmotm.git] / drivers / misc / ad525x_dpot.c
blob30a59f2bacd2a58f61abb25a4bfcbc28c046f61a
1 /*
2 * ad525x_dpot: Driver for the Analog Devices AD525x digital potentiometers
3 * Copyright (c) 2009 Analog Devices, Inc.
4 * Author: Michael Hennerich <hennerich@blackfin.uclinux.org>
6 * DEVID #Wipers #Positions Resistor Options (kOhm)
7 * AD5258 1 64 1, 10, 50, 100
8 * AD5259 1 256 5, 10, 50, 100
9 * AD5251 2 64 1, 10, 50, 100
10 * AD5252 2 256 1, 10, 50, 100
11 * AD5255 3 512 25, 250
12 * AD5253 4 64 1, 10, 50, 100
13 * AD5254 4 256 1, 10, 50, 100
15 * See Documentation/misc-devices/ad525x_dpot.txt for more info.
17 * derived from ad5258.c
18 * Copyright (c) 2009 Cyber Switching, Inc.
19 * Author: Chris Verges <chrisv@cyberswitching.com>
21 * derived from ad5252.c
22 * Copyright (c) 2006 Michael Hennerich <hennerich@blackfin.uclinux.org>
24 * Licensed under the GPL-2 or later.
27 #include <linux/module.h>
28 #include <linux/device.h>
29 #include <linux/kernel.h>
30 #include <linux/init.h>
31 #include <linux/slab.h>
32 #include <linux/i2c.h>
33 #include <linux/delay.h>
35 #define DRIVER_NAME "ad525x_dpot"
36 #define DRIVER_VERSION "0.1"
38 enum dpot_devid {
39 AD5258_ID,
40 AD5259_ID,
41 AD5251_ID,
42 AD5252_ID,
43 AD5253_ID,
44 AD5254_ID,
45 AD5255_ID,
48 #define AD5258_MAX_POSITION 64
49 #define AD5259_MAX_POSITION 256
50 #define AD5251_MAX_POSITION 64
51 #define AD5252_MAX_POSITION 256
52 #define AD5253_MAX_POSITION 64
53 #define AD5254_MAX_POSITION 256
54 #define AD5255_MAX_POSITION 512
56 #define AD525X_RDAC0 0
57 #define AD525X_RDAC1 1
58 #define AD525X_RDAC2 2
59 #define AD525X_RDAC3 3
61 #define AD525X_REG_TOL 0x18
62 #define AD525X_TOL_RDAC0 (AD525X_REG_TOL | AD525X_RDAC0)
63 #define AD525X_TOL_RDAC1 (AD525X_REG_TOL | AD525X_RDAC1)
64 #define AD525X_TOL_RDAC2 (AD525X_REG_TOL | AD525X_RDAC2)
65 #define AD525X_TOL_RDAC3 (AD525X_REG_TOL | AD525X_RDAC3)
67 /* RDAC-to-EEPROM Interface Commands */
68 #define AD525X_I2C_RDAC (0x00 << 5)
69 #define AD525X_I2C_EEPROM (0x01 << 5)
70 #define AD525X_I2C_CMD (0x80)
72 #define AD525X_DEC_ALL_6DB (AD525X_I2C_CMD | (0x4 << 3))
73 #define AD525X_INC_ALL_6DB (AD525X_I2C_CMD | (0x9 << 3))
74 #define AD525X_DEC_ALL (AD525X_I2C_CMD | (0x6 << 3))
75 #define AD525X_INC_ALL (AD525X_I2C_CMD | (0xB << 3))
77 static s32 ad525x_read(struct i2c_client *client, u8 reg);
78 static s32 ad525x_write(struct i2c_client *client, u8 reg, u8 value);
81 * Client data (each client gets its own)
84 struct dpot_data {
85 struct mutex update_lock;
86 unsigned rdac_mask;
87 unsigned max_pos;
88 unsigned devid;
91 /* sysfs functions */
93 static ssize_t sysfs_show_reg(struct device *dev,
94 struct device_attribute *attr, char *buf, u32 reg)
96 struct i2c_client *client = to_i2c_client(dev);
97 struct dpot_data *data = i2c_get_clientdata(client);
98 s32 value;
100 mutex_lock(&data->update_lock);
101 value = ad525x_read(client, reg);
102 mutex_unlock(&data->update_lock);
104 if (value < 0)
105 return -EINVAL;
107 * Let someone else deal with converting this ...
108 * the tolerance is a two-byte value where the MSB
109 * is a sign + integer value, and the LSB is a
110 * decimal value. See page 18 of the AD5258
111 * datasheet (Rev. A) for more details.
114 if (reg & AD525X_REG_TOL)
115 return sprintf(buf, "0x%04x\n", value & 0xFFFF);
116 else
117 return sprintf(buf, "%u\n", value & data->rdac_mask);
120 static ssize_t sysfs_set_reg(struct device *dev,
121 struct device_attribute *attr,
122 const char *buf, size_t count, u32 reg)
124 struct i2c_client *client = to_i2c_client(dev);
125 struct dpot_data *data = i2c_get_clientdata(client);
126 unsigned long value;
127 int err;
129 err = strict_strtoul(buf, 10, &value);
130 if (err)
131 return err;
133 if (value > data->rdac_mask)
134 value = data->rdac_mask;
136 mutex_lock(&data->update_lock);
137 ad525x_write(client, reg, value);
138 if (reg & AD525X_I2C_EEPROM)
139 msleep(26); /* Sleep while the EEPROM updates */
140 mutex_unlock(&data->update_lock);
142 return count;
145 static ssize_t sysfs_do_cmd(struct device *dev,
146 struct device_attribute *attr,
147 const char *buf, size_t count, u32 reg)
149 struct i2c_client *client = to_i2c_client(dev);
150 struct dpot_data *data = i2c_get_clientdata(client);
152 mutex_lock(&data->update_lock);
153 ad525x_write(client, reg, 0);
154 mutex_unlock(&data->update_lock);
156 return count;
159 /* ------------------------------------------------------------------------- */
161 static ssize_t show_rdac0(struct device *dev,
162 struct device_attribute *attr, char *buf)
164 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC0);
167 static ssize_t set_rdac0(struct device *dev,
168 struct device_attribute *attr,
169 const char *buf, size_t count)
171 return sysfs_set_reg(dev, attr, buf, count,
172 AD525X_I2C_RDAC | AD525X_RDAC0);
175 static DEVICE_ATTR(rdac0, S_IWUSR | S_IRUGO, show_rdac0, set_rdac0);
177 static ssize_t show_eeprom0(struct device *dev,
178 struct device_attribute *attr, char *buf)
180 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC0);
183 static ssize_t set_eeprom0(struct device *dev,
184 struct device_attribute *attr,
185 const char *buf, size_t count)
187 return sysfs_set_reg(dev, attr, buf, count,
188 AD525X_I2C_EEPROM | AD525X_RDAC0);
191 static DEVICE_ATTR(eeprom0, S_IWUSR | S_IRUGO, show_eeprom0, set_eeprom0);
193 static ssize_t show_tolerance0(struct device *dev,
194 struct device_attribute *attr, char *buf)
196 return sysfs_show_reg(dev, attr, buf,
197 AD525X_I2C_EEPROM | AD525X_TOL_RDAC0);
200 static DEVICE_ATTR(tolerance0, S_IRUGO, show_tolerance0, NULL);
202 /* ------------------------------------------------------------------------- */
204 static ssize_t show_rdac1(struct device *dev,
205 struct device_attribute *attr, char *buf)
207 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC1);
210 static ssize_t set_rdac1(struct device *dev,
211 struct device_attribute *attr,
212 const char *buf, size_t count)
214 return sysfs_set_reg(dev, attr, buf, count,
215 AD525X_I2C_RDAC | AD525X_RDAC1);
218 static DEVICE_ATTR(rdac1, S_IWUSR | S_IRUGO, show_rdac1, set_rdac1);
220 static ssize_t show_eeprom1(struct device *dev,
221 struct device_attribute *attr, char *buf)
223 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC1);
226 static ssize_t set_eeprom1(struct device *dev,
227 struct device_attribute *attr,
228 const char *buf, size_t count)
230 return sysfs_set_reg(dev, attr, buf, count,
231 AD525X_I2C_EEPROM | AD525X_RDAC1);
234 static DEVICE_ATTR(eeprom1, S_IWUSR | S_IRUGO, show_eeprom1, set_eeprom1);
236 static ssize_t show_tolerance1(struct device *dev,
237 struct device_attribute *attr, char *buf)
239 return sysfs_show_reg(dev, attr, buf,
240 AD525X_I2C_EEPROM | AD525X_TOL_RDAC1);
243 static DEVICE_ATTR(tolerance1, S_IRUGO, show_tolerance1, NULL);
245 /* ------------------------------------------------------------------------- */
247 static ssize_t show_rdac2(struct device *dev,
248 struct device_attribute *attr, char *buf)
250 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC2);
253 static ssize_t set_rdac2(struct device *dev,
254 struct device_attribute *attr,
255 const char *buf, size_t count)
257 return sysfs_set_reg(dev, attr, buf, count,
258 AD525X_I2C_RDAC | AD525X_RDAC2);
261 static DEVICE_ATTR(rdac2, S_IWUSR | S_IRUGO, show_rdac2, set_rdac2);
263 static ssize_t show_eeprom2(struct device *dev,
264 struct device_attribute *attr, char *buf)
266 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC2);
269 static ssize_t set_eeprom2(struct device *dev,
270 struct device_attribute *attr,
271 const char *buf, size_t count)
273 return sysfs_set_reg(dev, attr, buf, count,
274 AD525X_I2C_EEPROM | AD525X_RDAC2);
277 static DEVICE_ATTR(eeprom2, S_IWUSR | S_IRUGO, show_eeprom2, set_eeprom2);
279 static ssize_t show_tolerance2(struct device *dev,
280 struct device_attribute *attr, char *buf)
282 return sysfs_show_reg(dev, attr, buf,
283 AD525X_I2C_EEPROM | AD525X_TOL_RDAC2);
286 static DEVICE_ATTR(tolerance2, S_IRUGO, show_tolerance2, NULL);
288 /* ------------------------------------------------------------------------- */
290 static ssize_t show_rdac3(struct device *dev,
291 struct device_attribute *attr, char *buf)
293 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC3);
296 static ssize_t set_rdac3(struct device *dev,
297 struct device_attribute *attr,
298 const char *buf, size_t count)
300 return sysfs_set_reg(dev, attr, buf, count,
301 AD525X_I2C_RDAC | AD525X_RDAC3);
304 static DEVICE_ATTR(rdac3, S_IWUSR | S_IRUGO, show_rdac3, set_rdac3);
306 static ssize_t show_eeprom3(struct device *dev,
307 struct device_attribute *attr, char *buf)
309 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC3);
312 static ssize_t set_eeprom3(struct device *dev,
313 struct device_attribute *attr,
314 const char *buf, size_t count)
316 return sysfs_set_reg(dev, attr, buf, count,
317 AD525X_I2C_EEPROM | AD525X_RDAC3);
320 static DEVICE_ATTR(eeprom3, S_IWUSR | S_IRUGO, show_eeprom3, set_eeprom3);
322 static ssize_t show_tolerance3(struct device *dev,
323 struct device_attribute *attr, char *buf)
325 return sysfs_show_reg(dev, attr, buf,
326 AD525X_I2C_EEPROM | AD525X_TOL_RDAC3);
329 static DEVICE_ATTR(tolerance3, S_IRUGO, show_tolerance3, NULL);
331 static struct attribute *ad525x_attributes_wipers[4][4] = {
333 &dev_attr_rdac0.attr,
334 &dev_attr_eeprom0.attr,
335 &dev_attr_tolerance0.attr,
336 NULL
337 }, {
338 &dev_attr_rdac1.attr,
339 &dev_attr_eeprom1.attr,
340 &dev_attr_tolerance1.attr,
341 NULL
342 }, {
343 &dev_attr_rdac2.attr,
344 &dev_attr_eeprom2.attr,
345 &dev_attr_tolerance2.attr,
346 NULL
347 }, {
348 &dev_attr_rdac3.attr,
349 &dev_attr_eeprom3.attr,
350 &dev_attr_tolerance3.attr,
351 NULL
355 static const struct attribute_group ad525x_group_wipers[] = {
356 {.attrs = ad525x_attributes_wipers[AD525X_RDAC0]},
357 {.attrs = ad525x_attributes_wipers[AD525X_RDAC1]},
358 {.attrs = ad525x_attributes_wipers[AD525X_RDAC2]},
359 {.attrs = ad525x_attributes_wipers[AD525X_RDAC3]},
362 /* ------------------------------------------------------------------------- */
364 static ssize_t set_inc_all(struct device *dev,
365 struct device_attribute *attr,
366 const char *buf, size_t count)
368 return sysfs_do_cmd(dev, attr, buf, count, AD525X_INC_ALL);
371 static DEVICE_ATTR(inc_all, S_IWUSR, NULL, set_inc_all);
373 static ssize_t set_dec_all(struct device *dev,
374 struct device_attribute *attr,
375 const char *buf, size_t count)
377 return sysfs_do_cmd(dev, attr, buf, count, AD525X_DEC_ALL);
380 static DEVICE_ATTR(dec_all, S_IWUSR, NULL, set_dec_all);
382 static ssize_t set_inc_all_6db(struct device *dev,
383 struct device_attribute *attr,
384 const char *buf, size_t count)
386 return sysfs_do_cmd(dev, attr, buf, count, AD525X_INC_ALL_6DB);
389 static DEVICE_ATTR(inc_all_6db, S_IWUSR, NULL, set_inc_all_6db);
391 static ssize_t set_dec_all_6db(struct device *dev,
392 struct device_attribute *attr,
393 const char *buf, size_t count)
395 return sysfs_do_cmd(dev, attr, buf, count, AD525X_DEC_ALL_6DB);
398 static DEVICE_ATTR(dec_all_6db, S_IWUSR, NULL, set_dec_all_6db);
400 static struct attribute *ad525x_attributes_commands[] = {
401 &dev_attr_inc_all.attr,
402 &dev_attr_dec_all.attr,
403 &dev_attr_inc_all_6db.attr,
404 &dev_attr_dec_all_6db.attr,
405 NULL
408 static const struct attribute_group ad525x_group_commands = {
409 .attrs = ad525x_attributes_commands,
412 /* ------------------------------------------------------------------------- */
414 /* i2c device functions */
417 * ad525x_read - return the value contained in the specified register
418 * on the AD5258 device.
419 * @client: value returned from i2c_new_device()
420 * @reg: the register to read
422 * If the tolerance register is specified, 2 bytes are returned.
423 * Otherwise, 1 byte is returned. A negative value indicates an error
424 * occurred while reading the register.
426 static s32 ad525x_read(struct i2c_client *client, u8 reg)
428 struct dpot_data *data = i2c_get_clientdata(client);
430 if ((reg & AD525X_REG_TOL) || (data->max_pos > 256))
431 return i2c_smbus_read_word_data(client, (reg & 0xF8) |
432 ((reg & 0x7) << 1));
433 else
434 return i2c_smbus_read_byte_data(client, reg);
438 * ad525x_write - store the given value in the specified register on
439 * the AD5258 device.
440 * @client: value returned from i2c_new_device()
441 * @reg: the register to write
442 * @value: the byte to store in the register
444 * For certain instructions that do not require a data byte, "NULL"
445 * should be specified for the "value" parameter. These instructions
446 * include NOP, RESTORE_FROM_EEPROM, and STORE_TO_EEPROM.
448 * A negative return value indicates an error occurred while reading
449 * the register.
451 static s32 ad525x_write(struct i2c_client *client, u8 reg, u8 value)
453 struct dpot_data *data = i2c_get_clientdata(client);
455 /* Only write the instruction byte for certain commands */
456 if (reg & AD525X_I2C_CMD)
457 return i2c_smbus_write_byte(client, reg);
459 if (data->max_pos > 256)
460 return i2c_smbus_write_word_data(client, (reg & 0xF8) |
461 ((reg & 0x7) << 1), value);
462 else
463 /* All other registers require instruction + data bytes */
464 return i2c_smbus_write_byte_data(client, reg, value);
467 static int ad525x_probe(struct i2c_client *client,
468 const struct i2c_device_id *id)
470 struct device *dev = &client->dev;
471 struct dpot_data *data;
472 int err = 0;
474 dev_dbg(dev, "%s\n", __func__);
476 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) {
477 dev_err(dev, "missing I2C functionality for this driver\n");
478 goto exit;
481 data = kzalloc(sizeof(struct dpot_data), GFP_KERNEL);
482 if (!data) {
483 err = -ENOMEM;
484 goto exit;
487 i2c_set_clientdata(client, data);
488 mutex_init(&data->update_lock);
490 switch (id->driver_data) {
491 case AD5258_ID:
492 data->max_pos = AD5258_MAX_POSITION;
493 err = sysfs_create_group(&dev->kobj,
494 &ad525x_group_wipers[AD525X_RDAC0]);
495 break;
496 case AD5259_ID:
497 data->max_pos = AD5259_MAX_POSITION;
498 err = sysfs_create_group(&dev->kobj,
499 &ad525x_group_wipers[AD525X_RDAC0]);
500 break;
501 case AD5251_ID:
502 data->max_pos = AD5251_MAX_POSITION;
503 err = sysfs_create_group(&dev->kobj,
504 &ad525x_group_wipers[AD525X_RDAC1]);
505 err |= sysfs_create_group(&dev->kobj,
506 &ad525x_group_wipers[AD525X_RDAC3]);
507 err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands);
508 break;
509 case AD5252_ID:
510 data->max_pos = AD5252_MAX_POSITION;
511 err = sysfs_create_group(&dev->kobj,
512 &ad525x_group_wipers[AD525X_RDAC1]);
513 err |= sysfs_create_group(&dev->kobj,
514 &ad525x_group_wipers[AD525X_RDAC3]);
515 err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands);
516 break;
517 case AD5253_ID:
518 data->max_pos = AD5253_MAX_POSITION;
519 err = sysfs_create_group(&dev->kobj,
520 &ad525x_group_wipers[AD525X_RDAC0]);
521 err |= sysfs_create_group(&dev->kobj,
522 &ad525x_group_wipers[AD525X_RDAC1]);
523 err |= sysfs_create_group(&dev->kobj,
524 &ad525x_group_wipers[AD525X_RDAC2]);
525 err |= sysfs_create_group(&dev->kobj,
526 &ad525x_group_wipers[AD525X_RDAC3]);
527 err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands);
528 break;
529 case AD5254_ID:
530 data->max_pos = AD5254_MAX_POSITION;
531 err = sysfs_create_group(&dev->kobj,
532 &ad525x_group_wipers[AD525X_RDAC0]);
533 err |= sysfs_create_group(&dev->kobj,
534 &ad525x_group_wipers[AD525X_RDAC1]);
535 err |= sysfs_create_group(&dev->kobj,
536 &ad525x_group_wipers[AD525X_RDAC2]);
537 err |= sysfs_create_group(&dev->kobj,
538 &ad525x_group_wipers[AD525X_RDAC3]);
539 err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands);
540 break;
541 case AD5255_ID:
542 data->max_pos = AD5255_MAX_POSITION;
543 err = sysfs_create_group(&dev->kobj,
544 &ad525x_group_wipers[AD525X_RDAC0]);
545 err |= sysfs_create_group(&dev->kobj,
546 &ad525x_group_wipers[AD525X_RDAC1]);
547 err |= sysfs_create_group(&dev->kobj,
548 &ad525x_group_wipers[AD525X_RDAC2]);
549 err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands);
550 break;
551 default:
552 err = -ENODEV;
553 goto exit_free;
556 if (err) {
557 dev_err(dev, "failed to register sysfs hooks\n");
558 goto exit_free;
561 data->devid = id->driver_data;
562 data->rdac_mask = data->max_pos - 1;
564 dev_info(dev, "%s %d-Position Digital Potentiometer registered\n",
565 id->name, data->max_pos);
567 return 0;
569 exit_free:
570 kfree(data);
571 i2c_set_clientdata(client, NULL);
572 exit:
573 dev_err(dev, "failed to create client\n");
574 return err;
577 static int __devexit ad525x_remove(struct i2c_client *client)
579 struct dpot_data *data = i2c_get_clientdata(client);
580 struct device *dev = &client->dev;
582 switch (data->devid) {
583 case AD5258_ID:
584 case AD5259_ID:
585 sysfs_remove_group(&dev->kobj,
586 &ad525x_group_wipers[AD525X_RDAC0]);
587 break;
588 case AD5251_ID:
589 case AD5252_ID:
590 sysfs_remove_group(&dev->kobj,
591 &ad525x_group_wipers[AD525X_RDAC1]);
592 sysfs_remove_group(&dev->kobj,
593 &ad525x_group_wipers[AD525X_RDAC3]);
594 sysfs_remove_group(&dev->kobj, &ad525x_group_commands);
595 break;
596 case AD5253_ID:
597 case AD5254_ID:
598 sysfs_remove_group(&dev->kobj,
599 &ad525x_group_wipers[AD525X_RDAC0]);
600 sysfs_remove_group(&dev->kobj,
601 &ad525x_group_wipers[AD525X_RDAC1]);
602 sysfs_remove_group(&dev->kobj,
603 &ad525x_group_wipers[AD525X_RDAC2]);
604 sysfs_remove_group(&dev->kobj,
605 &ad525x_group_wipers[AD525X_RDAC3]);
606 sysfs_remove_group(&dev->kobj, &ad525x_group_commands);
607 break;
608 case AD5255_ID:
609 sysfs_remove_group(&dev->kobj,
610 &ad525x_group_wipers[AD525X_RDAC0]);
611 sysfs_remove_group(&dev->kobj,
612 &ad525x_group_wipers[AD525X_RDAC1]);
613 sysfs_remove_group(&dev->kobj,
614 &ad525x_group_wipers[AD525X_RDAC2]);
615 sysfs_remove_group(&dev->kobj, &ad525x_group_commands);
616 break;
619 i2c_set_clientdata(client, NULL);
620 kfree(data);
622 return 0;
625 static const struct i2c_device_id ad525x_idtable[] = {
626 {"ad5258", AD5258_ID},
627 {"ad5259", AD5259_ID},
628 {"ad5251", AD5251_ID},
629 {"ad5252", AD5252_ID},
630 {"ad5253", AD5253_ID},
631 {"ad5254", AD5254_ID},
632 {"ad5255", AD5255_ID},
636 MODULE_DEVICE_TABLE(i2c, ad525x_idtable);
638 static struct i2c_driver ad525x_driver = {
639 .driver = {
640 .owner = THIS_MODULE,
641 .name = DRIVER_NAME,
643 .id_table = ad525x_idtable,
644 .probe = ad525x_probe,
645 .remove = __devexit_p(ad525x_remove),
648 static int __init ad525x_init(void)
650 return i2c_add_driver(&ad525x_driver);
653 module_init(ad525x_init);
655 static void __exit ad525x_exit(void)
657 i2c_del_driver(&ad525x_driver);
660 module_exit(ad525x_exit);
662 MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>, "
663 "Michael Hennerich <hennerich@blackfin.uclinux.org>, ");
664 MODULE_DESCRIPTION("AD5258/9 digital potentiometer driver");
665 MODULE_LICENSE("GPL");
666 MODULE_VERSION(DRIVER_VERSION);