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