aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/ad525x_dpot.c
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2010-05-24 17:33:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-25 11:07:04 -0400
commit59592d0ccc0000d74ea5fc2a59e3ec0c9ef1fb13 (patch)
tree7a871ad14dfd9e438684787332663fba6f4db7ed /drivers/misc/ad525x_dpot.c
parentc74cba610c9559e72377fd9725a3d329581aa256 (diff)
ad525x_dpot: add support for one time programmable pots
New parts supported: AD5170, AD5171, AD5172, AD5173, AD5273 Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc/ad525x_dpot.c')
-rw-r--r--drivers/misc/ad525x_dpot.c121
1 files changed, 116 insertions, 5 deletions
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c
index 255ba4b5e355..5e6fa8449e8b 100644
--- a/drivers/misc/ad525x_dpot.c
+++ b/drivers/misc/ad525x_dpot.c
@@ -47,6 +47,11 @@
47 * AD5280 1 256 20, 50, 200 47 * AD5280 1 256 20, 50, 200
48 * AD5282 2 256 20, 50, 200 48 * AD5282 2 256 20, 50, 200
49 * ADN2860 3 512 25, 250 49 * ADN2860 3 512 25, 250
50 * AD5273 1 64 1, 10, 50, 100 (OTP)
51 * AD5171 1 64 5, 10, 50, 100 (OTP)
52 * AD5170 1 256 2.5, 10, 50, 100 (OTP)
53 * AD5172 2 256 2.5, 10, 50, 100 (OTP)
54 * AD5173 2 256 2.5, 10, 50, 100 (OTP)
50 * 55 *
51 * See Documentation/misc-devices/ad525x_dpot.txt for more info. 56 * See Documentation/misc-devices/ad525x_dpot.txt for more info.
52 * 57 *
@@ -84,7 +89,8 @@ struct dpot_data {
84 unsigned uid; 89 unsigned uid;
85 unsigned feat; 90 unsigned feat;
86 unsigned wipers; 91 unsigned wipers;
87 u16 rdac_cache[8]; 92 u16 rdac_cache[MAX_RDACS];
93 DECLARE_BITMAP(otp_en_mask, MAX_RDACS);
88}; 94};
89 95
90static inline int dpot_read_d8(struct dpot_data *dpot) 96static inline int dpot_read_d8(struct dpot_data *dpot)
@@ -162,6 +168,15 @@ static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
162 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ? 168 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
163 0 : DPOT_AD5291_RDAC_AB; 169 0 : DPOT_AD5291_RDAC_AB;
164 return dpot_read_r8d8(dpot, ctrl); 170 return dpot_read_r8d8(dpot, ctrl);
171 case DPOT_UID(AD5170_ID):
172 case DPOT_UID(AD5171_ID):
173 case DPOT_UID(AD5273_ID):
174 return dpot_read_d8(dpot);
175 case DPOT_UID(AD5172_ID):
176 case DPOT_UID(AD5173_ID):
177 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
178 0 : DPOT_AD5272_3_A0;
179 return dpot_read_r8d8(dpot, ctrl);
165 default: 180 default:
166 if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256)) 181 if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256))
167 return dpot_read_r8d16(dpot, (reg & 0xF8) | 182 return dpot_read_r8d16(dpot, (reg & 0xF8) |
@@ -242,7 +257,7 @@ static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
242static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value) 257static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
243{ 258{
244 /* Only write the instruction byte for certain commands */ 259 /* Only write the instruction byte for certain commands */
245 unsigned ctrl = 0; 260 unsigned tmp = 0, ctrl = 0;
246 261
247 switch (dpot->uid) { 262 switch (dpot->uid) {
248 case DPOT_UID(AD5246_ID): 263 case DPOT_UID(AD5246_ID):
@@ -261,6 +276,37 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
261 0 : DPOT_AD5291_RDAC_AB; 276 0 : DPOT_AD5291_RDAC_AB;
262 return dpot_write_r8d8(dpot, ctrl, value); 277 return dpot_write_r8d8(dpot, ctrl, value);
263 break; 278 break;
279 case DPOT_UID(AD5171_ID):
280 case DPOT_UID(AD5273_ID):
281 if (reg & DPOT_ADDR_OTP) {
282 tmp = dpot_read_d8(dpot);
283 if (tmp >> 6) /* Ready to Program? */
284 return -EFAULT;
285 ctrl = DPOT_AD5273_FUSE;
286 }
287 return dpot_write_r8d8(dpot, ctrl, value);
288 break;
289 case DPOT_UID(AD5172_ID):
290 case DPOT_UID(AD5173_ID):
291 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
292 0 : DPOT_AD5272_3_A0;
293 if (reg & DPOT_ADDR_OTP) {
294 tmp = dpot_read_r8d16(dpot, ctrl);
295 if (tmp >> 14) /* Ready to Program? */
296 return -EFAULT;
297 ctrl |= DPOT_AD5270_2_3_FUSE;
298 }
299 return dpot_write_r8d8(dpot, ctrl, value);
300 break;
301 case DPOT_UID(AD5170_ID):
302 if (reg & DPOT_ADDR_OTP) {
303 tmp = dpot_read_r8d16(dpot, tmp);
304 if (tmp >> 14) /* Ready to Program? */
305 return -EFAULT;
306 ctrl = DPOT_AD5270_2_3_FUSE;
307 }
308 return dpot_write_r8d8(dpot, ctrl, value);
309 break;
264 default: 310 default:
265 if (reg & DPOT_ADDR_CMD) 311 if (reg & DPOT_ADDR_CMD)
266 return dpot_write_d8(dpot, reg); 312 return dpot_write_d8(dpot, reg);
@@ -292,6 +338,12 @@ static ssize_t sysfs_show_reg(struct device *dev,
292 struct dpot_data *data = dev_get_drvdata(dev); 338 struct dpot_data *data = dev_get_drvdata(dev);
293 s32 value; 339 s32 value;
294 340
341 if (reg & DPOT_ADDR_OTP_EN)
342 return sprintf(buf, "%s\n",
343 test_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask) ?
344 "enabled" : "disabled");
345
346
295 mutex_lock(&data->update_lock); 347 mutex_lock(&data->update_lock);
296 value = dpot_read(data, reg); 348 value = dpot_read(data, reg);
297 mutex_unlock(&data->update_lock); 349 mutex_unlock(&data->update_lock);
@@ -320,6 +372,19 @@ static ssize_t sysfs_set_reg(struct device *dev,
320 unsigned long value; 372 unsigned long value;
321 int err; 373 int err;
322 374
375 if (reg & DPOT_ADDR_OTP_EN) {
376 if (!strncmp(buf, "enabled", sizeof("enabled")))
377 set_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask);
378 else
379 clear_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask);
380
381 return count;
382 }
383
384 if ((reg & DPOT_ADDR_OTP) &&
385 !test_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask))
386 return -EPERM;
387
323 err = strict_strtoul(buf, 10, &value); 388 err = strict_strtoul(buf, 10, &value);
324 if (err) 389 if (err)
325 return err; 390 return err;
@@ -331,6 +396,8 @@ static ssize_t sysfs_set_reg(struct device *dev,
331 dpot_write(data, reg, value); 396 dpot_write(data, reg, value);
332 if (reg & DPOT_ADDR_EEPROM) 397 if (reg & DPOT_ADDR_EEPROM)
333 msleep(26); /* Sleep while the EEPROM updates */ 398 msleep(26); /* Sleep while the EEPROM updates */
399 else if (reg & DPOT_ADDR_OTP)
400 msleep(400); /* Sleep while the OTP updates */
334 mutex_unlock(&data->update_lock); 401 mutex_unlock(&data->update_lock);
335 402
336 return count; 403 return count;
@@ -378,26 +445,38 @@ static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, show_##name, NULL);
378DPOT_DEVICE_SHOW_SET(rdac0, DPOT_ADDR_RDAC | DPOT_RDAC0); 445DPOT_DEVICE_SHOW_SET(rdac0, DPOT_ADDR_RDAC | DPOT_RDAC0);
379DPOT_DEVICE_SHOW_SET(eeprom0, DPOT_ADDR_EEPROM | DPOT_RDAC0); 446DPOT_DEVICE_SHOW_SET(eeprom0, DPOT_ADDR_EEPROM | DPOT_RDAC0);
380DPOT_DEVICE_SHOW_ONLY(tolerance0, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC0); 447DPOT_DEVICE_SHOW_ONLY(tolerance0, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC0);
448DPOT_DEVICE_SHOW_SET(otp0, DPOT_ADDR_OTP | DPOT_RDAC0);
449DPOT_DEVICE_SHOW_SET(otp0en, DPOT_ADDR_OTP_EN | DPOT_RDAC0);
381 450
382DPOT_DEVICE_SHOW_SET(rdac1, DPOT_ADDR_RDAC | DPOT_RDAC1); 451DPOT_DEVICE_SHOW_SET(rdac1, DPOT_ADDR_RDAC | DPOT_RDAC1);
383DPOT_DEVICE_SHOW_SET(eeprom1, DPOT_ADDR_EEPROM | DPOT_RDAC1); 452DPOT_DEVICE_SHOW_SET(eeprom1, DPOT_ADDR_EEPROM | DPOT_RDAC1);
384DPOT_DEVICE_SHOW_ONLY(tolerance1, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC1); 453DPOT_DEVICE_SHOW_ONLY(tolerance1, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC1);
454DPOT_DEVICE_SHOW_SET(otp1, DPOT_ADDR_OTP | DPOT_RDAC1);
455DPOT_DEVICE_SHOW_SET(otp1en, DPOT_ADDR_OTP_EN | DPOT_RDAC1);
385 456
386DPOT_DEVICE_SHOW_SET(rdac2, DPOT_ADDR_RDAC | DPOT_RDAC2); 457DPOT_DEVICE_SHOW_SET(rdac2, DPOT_ADDR_RDAC | DPOT_RDAC2);
387DPOT_DEVICE_SHOW_SET(eeprom2, DPOT_ADDR_EEPROM | DPOT_RDAC2); 458DPOT_DEVICE_SHOW_SET(eeprom2, DPOT_ADDR_EEPROM | DPOT_RDAC2);
388DPOT_DEVICE_SHOW_ONLY(tolerance2, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC2); 459DPOT_DEVICE_SHOW_ONLY(tolerance2, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC2);
460DPOT_DEVICE_SHOW_SET(otp2, DPOT_ADDR_OTP | DPOT_RDAC2);
461DPOT_DEVICE_SHOW_SET(otp2en, DPOT_ADDR_OTP_EN | DPOT_RDAC2);
389 462
390DPOT_DEVICE_SHOW_SET(rdac3, DPOT_ADDR_RDAC | DPOT_RDAC3); 463DPOT_DEVICE_SHOW_SET(rdac3, DPOT_ADDR_RDAC | DPOT_RDAC3);
391DPOT_DEVICE_SHOW_SET(eeprom3, DPOT_ADDR_EEPROM | DPOT_RDAC3); 464DPOT_DEVICE_SHOW_SET(eeprom3, DPOT_ADDR_EEPROM | DPOT_RDAC3);
392DPOT_DEVICE_SHOW_ONLY(tolerance3, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC3); 465DPOT_DEVICE_SHOW_ONLY(tolerance3, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC3);
466DPOT_DEVICE_SHOW_SET(otp3, DPOT_ADDR_OTP | DPOT_RDAC3);
467DPOT_DEVICE_SHOW_SET(otp3en, DPOT_ADDR_OTP_EN | DPOT_RDAC3);
393 468
394DPOT_DEVICE_SHOW_SET(rdac4, DPOT_ADDR_RDAC | DPOT_RDAC4); 469DPOT_DEVICE_SHOW_SET(rdac4, DPOT_ADDR_RDAC | DPOT_RDAC4);
395DPOT_DEVICE_SHOW_SET(eeprom4, DPOT_ADDR_EEPROM | DPOT_RDAC4); 470DPOT_DEVICE_SHOW_SET(eeprom4, DPOT_ADDR_EEPROM | DPOT_RDAC4);
396DPOT_DEVICE_SHOW_ONLY(tolerance4, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC4); 471DPOT_DEVICE_SHOW_ONLY(tolerance4, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC4);
472DPOT_DEVICE_SHOW_SET(otp4, DPOT_ADDR_OTP | DPOT_RDAC4);
473DPOT_DEVICE_SHOW_SET(otp4en, DPOT_ADDR_OTP_EN | DPOT_RDAC4);
397 474
398DPOT_DEVICE_SHOW_SET(rdac5, DPOT_ADDR_RDAC | DPOT_RDAC5); 475DPOT_DEVICE_SHOW_SET(rdac5, DPOT_ADDR_RDAC | DPOT_RDAC5);
399DPOT_DEVICE_SHOW_SET(eeprom5, DPOT_ADDR_EEPROM | DPOT_RDAC5); 476DPOT_DEVICE_SHOW_SET(eeprom5, DPOT_ADDR_EEPROM | DPOT_RDAC5);
400DPOT_DEVICE_SHOW_ONLY(tolerance5, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC5); 477DPOT_DEVICE_SHOW_ONLY(tolerance5, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC5);
478DPOT_DEVICE_SHOW_SET(otp5, DPOT_ADDR_OTP | DPOT_RDAC5);
479DPOT_DEVICE_SHOW_SET(otp5en, DPOT_ADDR_OTP_EN | DPOT_RDAC5);
401 480
402static const struct attribute *dpot_attrib_wipers[] = { 481static const struct attribute *dpot_attrib_wipers[] = {
403 &dev_attr_rdac0.attr, 482 &dev_attr_rdac0.attr,
@@ -419,6 +498,26 @@ static const struct attribute *dpot_attrib_eeprom[] = {
419 NULL 498 NULL
420}; 499};
421 500
501static const struct attribute *dpot_attrib_otp[] = {
502 &dev_attr_otp0.attr,
503 &dev_attr_otp1.attr,
504 &dev_attr_otp2.attr,
505 &dev_attr_otp3.attr,
506 &dev_attr_otp4.attr,
507 &dev_attr_otp5.attr,
508 NULL
509};
510
511static const struct attribute *dpot_attrib_otp_en[] = {
512 &dev_attr_otp0en.attr,
513 &dev_attr_otp1en.attr,
514 &dev_attr_otp2en.attr,
515 &dev_attr_otp3en.attr,
516 &dev_attr_otp4en.attr,
517 &dev_attr_otp5en.attr,
518 NULL
519};
520
422static const struct attribute *dpot_attrib_tolerance[] = { 521static const struct attribute *dpot_attrib_tolerance[] = {
423 &dev_attr_tolerance0.attr, 522 &dev_attr_tolerance0.attr,
424 &dev_attr_tolerance1.attr, 523 &dev_attr_tolerance1.attr,
@@ -468,6 +567,12 @@ __devinit int ad_dpot_add_files(struct device *dev,
468 if (features & F_CMD_TOL) 567 if (features & F_CMD_TOL)
469 err |= sysfs_create_file(&dev->kobj, 568 err |= sysfs_create_file(&dev->kobj,
470 dpot_attrib_tolerance[rdac]); 569 dpot_attrib_tolerance[rdac]);
570 if (features & F_CMD_OTP) {
571 err |= sysfs_create_file(&dev->kobj,
572 dpot_attrib_otp_en[rdac]);
573 err |= sysfs_create_file(&dev->kobj,
574 dpot_attrib_otp[rdac]);
575 }
471 576
472 if (err) 577 if (err)
473 dev_err(dev, "failed to register sysfs hooks for RDAC%d\n", 578 dev_err(dev, "failed to register sysfs hooks for RDAC%d\n",
@@ -487,6 +592,12 @@ inline void ad_dpot_remove_files(struct device *dev,
487 if (features & F_CMD_TOL) 592 if (features & F_CMD_TOL)
488 sysfs_remove_file(&dev->kobj, 593 sysfs_remove_file(&dev->kobj,
489 dpot_attrib_tolerance[rdac]); 594 dpot_attrib_tolerance[rdac]);
595 if (features & F_CMD_OTP) {
596 sysfs_remove_file(&dev->kobj,
597 dpot_attrib_otp_en[rdac]);
598 sysfs_remove_file(&dev->kobj,
599 dpot_attrib_otp[rdac]);
600 }
490} 601}
491 602
492__devinit int ad_dpot_probe(struct device *dev, 603__devinit int ad_dpot_probe(struct device *dev,
@@ -514,7 +625,7 @@ __devinit int ad_dpot_probe(struct device *dev,
514 data->uid = DPOT_UID(data->devid); 625 data->uid = DPOT_UID(data->devid);
515 data->wipers = DPOT_WIPERS(data->devid); 626 data->wipers = DPOT_WIPERS(data->devid);
516 627
517 for (i = DPOT_RDAC0; i <= DPOT_RDAC5; i++) 628 for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
518 if (data->wipers & (1 << i)) { 629 if (data->wipers & (1 << i)) {
519 err = ad_dpot_add_files(dev, data->feat, i); 630 err = ad_dpot_add_files(dev, data->feat, i);
520 if (err) 631 if (err)
@@ -538,7 +649,7 @@ __devinit int ad_dpot_probe(struct device *dev,
538 return 0; 649 return 0;
539 650
540exit_remove_files: 651exit_remove_files:
541 for (i = DPOT_RDAC0; i <= DPOT_RDAC5; i++) 652 for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
542 if (data->wipers & (1 << i)) 653 if (data->wipers & (1 << i))
543 ad_dpot_remove_files(dev, data->feat, i); 654 ad_dpot_remove_files(dev, data->feat, i);
544 655
@@ -557,7 +668,7 @@ __devexit int ad_dpot_remove(struct device *dev)
557 struct dpot_data *data = dev_get_drvdata(dev); 668 struct dpot_data *data = dev_get_drvdata(dev);
558 int i; 669 int i;
559 670
560 for (i = DPOT_RDAC0; i <= DPOT_RDAC5; i++) 671 for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
561 if (data->wipers & (1 << i)) 672 if (data->wipers & (1 << i))
562 ad_dpot_remove_files(dev, data->feat, i); 673 ad_dpot_remove_files(dev, data->feat, i);
563 674