ad525x_dpot: add support for ADN2860 and AD528x pots
[linux-2.6.git] / drivers / misc / ad525x_dpot.c
1 /*
2  * ad525x_dpot: Driver for the Analog Devices digital potentiometers
3  * Copyright (c) 2009-2010 Analog Devices, Inc.
4  * Author: Michael Hennerich <hennerich@blackfin.uclinux.org>
5  *
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
14  * AD5160               1               256             5, 10, 50, 100
15  * AD5161               1               256             5, 10, 50, 100
16  * AD5162               2               256             2.5, 10, 50, 100
17  * AD5165               1               256             100
18  * AD5200               1               256             10, 50
19  * AD5201               1               33              10, 50
20  * AD5203               4               64              10, 100
21  * AD5204               4               256             10, 50, 100
22  * AD5206               6               256             10, 50, 100
23  * AD5207               2               256             10, 50, 100
24  * AD5231               1               1024            10, 50, 100
25  * AD5232               2               256             10, 50, 100
26  * AD5233               4               64              10, 50, 100
27  * AD5235               2               1024            25, 250
28  * AD5260               1               256             20, 50, 200
29  * AD5262               2               256             20, 50, 200
30  * AD5263               4               256             20, 50, 200
31  * AD5290               1               256             10, 50, 100
32  * AD5291               1               256             20
33  * AD5292               1               1024            20
34  * AD5293               1               1024            20
35  * AD7376               1               128             10, 50, 100, 1M
36  * AD8400               1               256             1, 10, 50, 100
37  * AD8402               2               256             1, 10, 50, 100
38  * AD8403               4               256             1, 10, 50, 100
39  * ADN2850              3               512             25, 250
40  * AD5241               1               256             10, 100, 1M
41  * AD5246               1               128             5, 10, 50, 100
42  * AD5247               1               128             5, 10, 50, 100
43  * AD5245               1               256             5, 10, 50, 100
44  * AD5243               2               256             2.5, 10, 50, 100
45  * AD5248               2               256             2.5, 10, 50, 100
46  * AD5242               2               256             20, 50, 200
47  * AD5280               1               256             20, 50, 200
48  * AD5282               2               256             20, 50, 200
49  * ADN2860              3               512             25, 250
50  *
51  * See Documentation/misc-devices/ad525x_dpot.txt for more info.
52  *
53  * derived from ad5258.c
54  * Copyright (c) 2009 Cyber Switching, Inc.
55  * Author: Chris Verges <chrisv@cyberswitching.com>
56  *
57  * derived from ad5252.c
58  * Copyright (c) 2006 Michael Hennerich <hennerich@blackfin.uclinux.org>
59  *
60  * Licensed under the GPL-2 or later.
61  */
62
63 #include <linux/module.h>
64 #include <linux/device.h>
65 #include <linux/kernel.h>
66 #include <linux/init.h>
67 #include <linux/delay.h>
68 #include <linux/slab.h>
69
70 #define DRIVER_VERSION                  "0.2"
71
72 #include "ad525x_dpot.h"
73
74 /*
75  * Client data (each client gets its own)
76  */
77
78 struct dpot_data {
79         struct ad_dpot_bus_data bdata;
80         struct mutex update_lock;
81         unsigned rdac_mask;
82         unsigned max_pos;
83         unsigned long devid;
84         unsigned uid;
85         unsigned feat;
86         unsigned wipers;
87         u16 rdac_cache[8];
88 };
89
90 static inline int dpot_read_d8(struct dpot_data *dpot)
91 {
92         return dpot->bdata.bops->read_d8(dpot->bdata.client);
93 }
94
95 static inline int dpot_read_r8d8(struct dpot_data *dpot, u8 reg)
96 {
97         return dpot->bdata.bops->read_r8d8(dpot->bdata.client, reg);
98 }
99
100 static inline int dpot_read_r8d16(struct dpot_data *dpot, u8 reg)
101 {
102         return dpot->bdata.bops->read_r8d16(dpot->bdata.client, reg);
103 }
104
105 static inline int dpot_write_d8(struct dpot_data *dpot, u8 val)
106 {
107         return dpot->bdata.bops->write_d8(dpot->bdata.client, val);
108 }
109
110 static inline int dpot_write_r8d8(struct dpot_data *dpot, u8 reg, u16 val)
111 {
112         return dpot->bdata.bops->write_r8d8(dpot->bdata.client, reg, val);
113 }
114
115 static inline int dpot_write_r8d16(struct dpot_data *dpot, u8 reg, u16 val)
116 {
117         return dpot->bdata.bops->write_r8d16(dpot->bdata.client, reg, val);
118 }
119
120 static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg)
121 {
122         unsigned ctrl = 0;
123
124         if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
125
126                 if (dpot->feat & F_RDACS_WONLY)
127                         return dpot->rdac_cache[reg & DPOT_RDAC_MASK];
128
129                 if (dpot->uid == DPOT_UID(AD5291_ID) ||
130                         dpot->uid == DPOT_UID(AD5292_ID) ||
131                         dpot->uid == DPOT_UID(AD5293_ID))
132                         return dpot_read_r8d8(dpot,
133                                 DPOT_AD5291_READ_RDAC << 2);
134
135                 ctrl = DPOT_SPI_READ_RDAC;
136         } else if (reg & DPOT_ADDR_EEPROM) {
137                 ctrl = DPOT_SPI_READ_EEPROM;
138         }
139
140         if (dpot->feat & F_SPI_16BIT)
141                 return dpot_read_r8d8(dpot, ctrl);
142         else if (dpot->feat & F_SPI_24BIT)
143                 return dpot_read_r8d16(dpot, ctrl);
144
145         return -EFAULT;
146 }
147
148 static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
149 {
150         unsigned ctrl = 0;
151         switch (dpot->uid) {
152         case DPOT_UID(AD5246_ID):
153         case DPOT_UID(AD5247_ID):
154                 return dpot_read_d8(dpot);
155         case DPOT_UID(AD5245_ID):
156         case DPOT_UID(AD5241_ID):
157         case DPOT_UID(AD5242_ID):
158         case DPOT_UID(AD5243_ID):
159         case DPOT_UID(AD5248_ID):
160         case DPOT_UID(AD5280_ID):
161         case DPOT_UID(AD5282_ID):
162                 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
163                         0 : DPOT_AD5291_RDAC_AB;
164                 return dpot_read_r8d8(dpot, ctrl);
165         default:
166                 if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256))
167                         return dpot_read_r8d16(dpot, (reg & 0xF8) |
168                                         ((reg & 0x7) << 1));
169                 else
170                         return dpot_read_r8d8(dpot, reg);
171         }
172 }
173
174 static s32 dpot_read(struct dpot_data *dpot, u8 reg)
175 {
176         if (dpot->feat & F_SPI)
177                 return dpot_read_spi(dpot, reg);
178         else
179                 return dpot_read_i2c(dpot, reg);
180 }
181
182 static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
183 {
184         unsigned val = 0;
185
186         if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
187                 if (dpot->feat & F_RDACS_WONLY)
188                         dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value;
189
190                 if (dpot->feat & F_AD_APPDATA) {
191                         if (dpot->feat & F_SPI_8BIT) {
192                                 val = ((reg & DPOT_RDAC_MASK) <<
193                                         DPOT_MAX_POS(dpot->devid)) |
194                                         value;
195                                 return dpot_write_d8(dpot, val);
196                         } else if (dpot->feat & F_SPI_16BIT) {
197                                 val = ((reg & DPOT_RDAC_MASK) <<
198                                         DPOT_MAX_POS(dpot->devid)) |
199                                         value;
200                                 return dpot_write_r8d8(dpot, val >> 8,
201                                         val & 0xFF);
202                         } else
203                                 BUG();
204                 } else {
205                         if (dpot->uid == DPOT_UID(AD5291_ID) ||
206                                 dpot->uid == DPOT_UID(AD5292_ID) ||
207                                 dpot->uid == DPOT_UID(AD5293_ID))
208                                 return dpot_write_r8d8(dpot,
209                                         (DPOT_AD5291_RDAC << 2) |
210                                         (value >> 8), value & 0xFF);
211
212                         val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK);
213                 }
214         } else if (reg & DPOT_ADDR_EEPROM) {
215                 val = DPOT_SPI_EEPROM | (reg & DPOT_RDAC_MASK);
216         } else if (reg & DPOT_ADDR_CMD) {
217                 switch (reg) {
218                 case DPOT_DEC_ALL_6DB:
219                         val = DPOT_SPI_DEC_ALL_6DB;
220                         break;
221                 case DPOT_INC_ALL_6DB:
222                         val = DPOT_SPI_INC_ALL_6DB;
223                         break;
224                 case DPOT_DEC_ALL:
225                         val = DPOT_SPI_DEC_ALL;
226                         break;
227                 case DPOT_INC_ALL:
228                         val = DPOT_SPI_INC_ALL;
229                         break;
230                 }
231         } else
232                 BUG();
233
234         if (dpot->feat & F_SPI_16BIT)
235                 return dpot_write_r8d8(dpot, val, value);
236         else if (dpot->feat & F_SPI_24BIT)
237                 return dpot_write_r8d16(dpot, val, value);
238
239         return -EFAULT;
240 }
241
242 static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
243 {
244         /* Only write the instruction byte for certain commands */
245         unsigned ctrl = 0;
246
247         switch (dpot->uid) {
248         case DPOT_UID(AD5246_ID):
249         case DPOT_UID(AD5247_ID):
250                 return dpot_write_d8(dpot, value);
251                 break;
252
253         case DPOT_UID(AD5245_ID):
254         case DPOT_UID(AD5241_ID):
255         case DPOT_UID(AD5242_ID):
256         case DPOT_UID(AD5243_ID):
257         case DPOT_UID(AD5248_ID):
258         case DPOT_UID(AD5280_ID):
259         case DPOT_UID(AD5282_ID):
260                 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
261                         0 : DPOT_AD5291_RDAC_AB;
262                 return dpot_write_r8d8(dpot, ctrl, value);
263                 break;
264         default:
265                 if (reg & DPOT_ADDR_CMD)
266                         return dpot_write_d8(dpot, reg);
267
268                 if (dpot->max_pos > 256)
269                         return dpot_write_r8d16(dpot, (reg & 0xF8) |
270                                                 ((reg & 0x7) << 1), value);
271                 else
272                         /* All other registers require instruction + data bytes */
273                         return dpot_write_r8d8(dpot, reg, value);
274         }
275 }
276
277
278 static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value)
279 {
280         if (dpot->feat & F_SPI)
281                 return dpot_write_spi(dpot, reg, value);
282         else
283                 return dpot_write_i2c(dpot, reg, value);
284 }
285
286 /* sysfs functions */
287
288 static ssize_t sysfs_show_reg(struct device *dev,
289                               struct device_attribute *attr,
290                               char *buf, u32 reg)
291 {
292         struct dpot_data *data = dev_get_drvdata(dev);
293         s32 value;
294
295         mutex_lock(&data->update_lock);
296         value = dpot_read(data, reg);
297         mutex_unlock(&data->update_lock);
298
299         if (value < 0)
300                 return -EINVAL;
301         /*
302          * Let someone else deal with converting this ...
303          * the tolerance is a two-byte value where the MSB
304          * is a sign + integer value, and the LSB is a
305          * decimal value.  See page 18 of the AD5258
306          * datasheet (Rev. A) for more details.
307          */
308
309         if (reg & DPOT_REG_TOL)
310                 return sprintf(buf, "0x%04x\n", value & 0xFFFF);
311         else
312                 return sprintf(buf, "%u\n", value & data->rdac_mask);
313 }
314
315 static ssize_t sysfs_set_reg(struct device *dev,
316                              struct device_attribute *attr,
317                              const char *buf, size_t count, u32 reg)
318 {
319         struct dpot_data *data = dev_get_drvdata(dev);
320         unsigned long value;
321         int err;
322
323         err = strict_strtoul(buf, 10, &value);
324         if (err)
325                 return err;
326
327         if (value > data->rdac_mask)
328                 value = data->rdac_mask;
329
330         mutex_lock(&data->update_lock);
331         dpot_write(data, reg, value);
332         if (reg & DPOT_ADDR_EEPROM)
333                 msleep(26);     /* Sleep while the EEPROM updates */
334         mutex_unlock(&data->update_lock);
335
336         return count;
337 }
338
339 static ssize_t sysfs_do_cmd(struct device *dev,
340                             struct device_attribute *attr,
341                             const char *buf, size_t count, u32 reg)
342 {
343         struct dpot_data *data = dev_get_drvdata(dev);
344
345         mutex_lock(&data->update_lock);
346         dpot_write(data, reg, 0);
347         mutex_unlock(&data->update_lock);
348
349         return count;
350 }
351
352 /* ------------------------------------------------------------------------- */
353
354 #define DPOT_DEVICE_SHOW(_name, _reg) static ssize_t \
355 show_##_name(struct device *dev, \
356                           struct device_attribute *attr, char *buf) \
357 { \
358         return sysfs_show_reg(dev, attr, buf, _reg); \
359 }
360
361 #define DPOT_DEVICE_SET(_name, _reg) static ssize_t \
362 set_##_name(struct device *dev, \
363                          struct device_attribute *attr, \
364                          const char *buf, size_t count) \
365 { \
366         return sysfs_set_reg(dev, attr, buf, count, _reg); \
367 }
368
369 #define DPOT_DEVICE_SHOW_SET(name, reg) \
370 DPOT_DEVICE_SHOW(name, reg) \
371 DPOT_DEVICE_SET(name, reg) \
372 static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, show_##name, set_##name);
373
374 #define DPOT_DEVICE_SHOW_ONLY(name, reg) \
375 DPOT_DEVICE_SHOW(name, reg) \
376 static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, show_##name, NULL);
377
378 DPOT_DEVICE_SHOW_SET(rdac0, DPOT_ADDR_RDAC | DPOT_RDAC0);
379 DPOT_DEVICE_SHOW_SET(eeprom0, DPOT_ADDR_EEPROM | DPOT_RDAC0);
380 DPOT_DEVICE_SHOW_ONLY(tolerance0, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC0);
381
382 DPOT_DEVICE_SHOW_SET(rdac1, DPOT_ADDR_RDAC | DPOT_RDAC1);
383 DPOT_DEVICE_SHOW_SET(eeprom1, DPOT_ADDR_EEPROM | DPOT_RDAC1);
384 DPOT_DEVICE_SHOW_ONLY(tolerance1, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC1);
385
386 DPOT_DEVICE_SHOW_SET(rdac2, DPOT_ADDR_RDAC | DPOT_RDAC2);
387 DPOT_DEVICE_SHOW_SET(eeprom2, DPOT_ADDR_EEPROM | DPOT_RDAC2);
388 DPOT_DEVICE_SHOW_ONLY(tolerance2, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC2);
389
390 DPOT_DEVICE_SHOW_SET(rdac3, DPOT_ADDR_RDAC | DPOT_RDAC3);
391 DPOT_DEVICE_SHOW_SET(eeprom3, DPOT_ADDR_EEPROM | DPOT_RDAC3);
392 DPOT_DEVICE_SHOW_ONLY(tolerance3, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC3);
393
394 DPOT_DEVICE_SHOW_SET(rdac4, DPOT_ADDR_RDAC | DPOT_RDAC4);
395 DPOT_DEVICE_SHOW_SET(eeprom4, DPOT_ADDR_EEPROM | DPOT_RDAC4);
396 DPOT_DEVICE_SHOW_ONLY(tolerance4, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC4);
397
398 DPOT_DEVICE_SHOW_SET(rdac5, DPOT_ADDR_RDAC | DPOT_RDAC5);
399 DPOT_DEVICE_SHOW_SET(eeprom5, DPOT_ADDR_EEPROM | DPOT_RDAC5);
400 DPOT_DEVICE_SHOW_ONLY(tolerance5, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC5);
401
402 static const struct attribute *dpot_attrib_wipers[] = {
403         &dev_attr_rdac0.attr,
404         &dev_attr_rdac1.attr,
405         &dev_attr_rdac2.attr,
406         &dev_attr_rdac3.attr,
407         &dev_attr_rdac4.attr,
408         &dev_attr_rdac5.attr,
409         NULL
410 };
411
412 static const struct attribute *dpot_attrib_eeprom[] = {
413         &dev_attr_eeprom0.attr,
414         &dev_attr_eeprom1.attr,
415         &dev_attr_eeprom2.attr,
416         &dev_attr_eeprom3.attr,
417         &dev_attr_eeprom4.attr,
418         &dev_attr_eeprom5.attr,
419         NULL
420 };
421
422 static const struct attribute *dpot_attrib_tolerance[] = {
423         &dev_attr_tolerance0.attr,
424         &dev_attr_tolerance1.attr,
425         &dev_attr_tolerance2.attr,
426         &dev_attr_tolerance3.attr,
427         &dev_attr_tolerance4.attr,
428         &dev_attr_tolerance5.attr,
429         NULL
430 };
431
432 /* ------------------------------------------------------------------------- */
433
434 #define DPOT_DEVICE_DO_CMD(_name, _cmd) static ssize_t \
435 set_##_name(struct device *dev, \
436                          struct device_attribute *attr, \
437                          const char *buf, size_t count) \
438 { \
439         return sysfs_do_cmd(dev, attr, buf, count, _cmd); \
440 } \
441 static DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, NULL, set_##_name);
442
443 DPOT_DEVICE_DO_CMD(inc_all, DPOT_INC_ALL);
444 DPOT_DEVICE_DO_CMD(dec_all, DPOT_DEC_ALL);
445 DPOT_DEVICE_DO_CMD(inc_all_6db, DPOT_INC_ALL_6DB);
446 DPOT_DEVICE_DO_CMD(dec_all_6db, DPOT_DEC_ALL_6DB);
447
448 static struct attribute *ad525x_attributes_commands[] = {
449         &dev_attr_inc_all.attr,
450         &dev_attr_dec_all.attr,
451         &dev_attr_inc_all_6db.attr,
452         &dev_attr_dec_all_6db.attr,
453         NULL
454 };
455
456 static const struct attribute_group ad525x_group_commands = {
457         .attrs = ad525x_attributes_commands,
458 };
459
460 __devinit int ad_dpot_add_files(struct device *dev,
461                 unsigned features, unsigned rdac)
462 {
463         int err = sysfs_create_file(&dev->kobj,
464                 dpot_attrib_wipers[rdac]);
465         if (features & F_CMD_EEP)
466                 err |= sysfs_create_file(&dev->kobj,
467                         dpot_attrib_eeprom[rdac]);
468         if (features & F_CMD_TOL)
469                 err |= sysfs_create_file(&dev->kobj,
470                         dpot_attrib_tolerance[rdac]);
471
472         if (err)
473                 dev_err(dev, "failed to register sysfs hooks for RDAC%d\n",
474                         rdac);
475
476         return err;
477 }
478
479 inline void ad_dpot_remove_files(struct device *dev,
480                 unsigned features, unsigned rdac)
481 {
482         sysfs_remove_file(&dev->kobj,
483                 dpot_attrib_wipers[rdac]);
484         if (features & F_CMD_EEP)
485                 sysfs_remove_file(&dev->kobj,
486                         dpot_attrib_eeprom[rdac]);
487         if (features & F_CMD_TOL)
488                 sysfs_remove_file(&dev->kobj,
489                         dpot_attrib_tolerance[rdac]);
490 }
491
492 __devinit int ad_dpot_probe(struct device *dev,
493                 struct ad_dpot_bus_data *bdata, const struct ad_dpot_id *id)
494 {
495
496         struct dpot_data *data;
497         int i, err = 0;
498
499         data = kzalloc(sizeof(struct dpot_data), GFP_KERNEL);
500         if (!data) {
501                 err = -ENOMEM;
502                 goto exit;
503         }
504
505         dev_set_drvdata(dev, data);
506         mutex_init(&data->update_lock);
507
508         data->bdata = *bdata;
509         data->devid = id->devid;
510
511         data->max_pos = 1 << DPOT_MAX_POS(data->devid);
512         data->rdac_mask = data->max_pos - 1;
513         data->feat = DPOT_FEAT(data->devid);
514         data->uid = DPOT_UID(data->devid);
515         data->wipers = DPOT_WIPERS(data->devid);
516
517         for (i = DPOT_RDAC0; i <= DPOT_RDAC5; i++)
518                 if (data->wipers & (1 << i)) {
519                         err = ad_dpot_add_files(dev, data->feat, i);
520                         if (err)
521                                 goto exit_remove_files;
522                         /* power-up midscale */
523                         if (data->feat & F_RDACS_WONLY)
524                                 data->rdac_cache[i] = data->max_pos / 2;
525                 }
526
527         if (data->feat & F_CMD_INC)
528                 err = sysfs_create_group(&dev->kobj, &ad525x_group_commands);
529
530         if (err) {
531                 dev_err(dev, "failed to register sysfs hooks\n");
532                 goto exit_free;
533         }
534
535         dev_info(dev, "%s %d-Position Digital Potentiometer registered\n",
536                  id->name, data->max_pos);
537
538         return 0;
539
540 exit_remove_files:
541         for (i = DPOT_RDAC0; i <= DPOT_RDAC5; i++)
542                 if (data->wipers & (1 << i))
543                         ad_dpot_remove_files(dev, data->feat, i);
544
545 exit_free:
546         kfree(data);
547         dev_set_drvdata(dev, NULL);
548 exit:
549         dev_err(dev, "failed to create client for %s ID 0x%lX\n",
550                         id->name, id->devid);
551         return err;
552 }
553 EXPORT_SYMBOL(ad_dpot_probe);
554
555 __devexit int ad_dpot_remove(struct device *dev)
556 {
557         struct dpot_data *data = dev_get_drvdata(dev);
558         int i;
559
560         for (i = DPOT_RDAC0; i <= DPOT_RDAC5; i++)
561                 if (data->wipers & (1 << i))
562                         ad_dpot_remove_files(dev, data->feat, i);
563
564         kfree(data);
565
566         return 0;
567 }
568 EXPORT_SYMBOL(ad_dpot_remove);
569
570
571 MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>, "
572               "Michael Hennerich <hennerich@blackfin.uclinux.org>");
573 MODULE_DESCRIPTION("Digital potentiometer driver");
574 MODULE_LICENSE("GPL");
575 MODULE_VERSION(DRIVER_VERSION);