aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/misc/Kconfig2
-rw-r--r--drivers/misc/ad525x_dpot-i2c.c5
-rw-r--r--drivers/misc/ad525x_dpot.c121
-rw-r--r--drivers/misc/ad525x_dpot.h42
4 files changed, 150 insertions, 20 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 233886d00861..26386a92f5aa 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -24,7 +24,7 @@ config AD525X_DPOT
24 AD5260, AD5262, AD5263, AD5290, AD5291, AD5292, AD5293, 24 AD5260, AD5262, AD5263, AD5290, AD5291, AD5292, AD5293,
25 AD7376, AD8400, AD8402, AD8403, ADN2850, AD5241, AD5242, 25 AD7376, AD8400, AD8402, AD8403, ADN2850, AD5241, AD5242,
26 AD5243, AD5245, AD5246, AD5247, AD5248, AD5280, AD5282, 26 AD5243, AD5245, AD5246, AD5247, AD5248, AD5280, AD5282,
27 ADN2860 27 ADN2860, AD5273, AD5171, AD5170, AD5172, AD5173
28 digital potentiometer chips. 28 digital potentiometer chips.
29 29
30 See Documentation/misc-devices/ad525x_dpot.txt for the 30 See Documentation/misc-devices/ad525x_dpot.txt for the
diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c
index abba18efdde3..374352af7979 100644
--- a/drivers/misc/ad525x_dpot-i2c.c
+++ b/drivers/misc/ad525x_dpot-i2c.c
@@ -97,6 +97,11 @@ static const struct i2c_device_id ad_dpot_id[] = {
97 {"ad5280", AD5280_ID}, 97 {"ad5280", AD5280_ID},
98 {"ad5282", AD5282_ID}, 98 {"ad5282", AD5282_ID},
99 {"adn2860", ADN2860_ID}, 99 {"adn2860", ADN2860_ID},
100 {"ad5273", AD5273_ID},
101 {"ad5171", AD5171_ID},
102 {"ad5170", AD5170_ID},
103 {"ad5172", AD5172_ID},
104 {"ad5173", AD5173_ID},
100 {} 105 {}
101}; 106};
102MODULE_DEVICE_TABLE(i2c, ad_dpot_id); 107MODULE_DEVICE_TABLE(i2c, ad_dpot_id);
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);