aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2010-10-26 17:22:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-26 19:52:14 -0400
commita4bd394956f20d0bfc0ca6ecfac2af4150da274a (patch)
tree5513a0ad4c7cedeb98fc0c521ff13d39752e729d /drivers/misc
parent5f400cf40fc703673aa791966ffb1c628c1ff45a (diff)
drivers/misc/ad525x_dpot.c: new features
Add support for AD5270, AD5271, AD5272, AD5274 digital potentiometers. Add 20-TP feature for AD5291 and AD5292 parts, and update feature list. AD5291 rdac read back must be shifted by two. Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Cc: Mike Frysinger <vapier@gentoo.org> Cc: Chris Verges <chrisv@cyberswitching.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig3
-rw-r--r--drivers/misc/ad525x_dpot-i2c.c2
-rw-r--r--drivers/misc/ad525x_dpot-spi.c2
-rw-r--r--drivers/misc/ad525x_dpot.c107
-rw-r--r--drivers/misc/ad525x_dpot.h23
5 files changed, 123 insertions, 14 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1f69743b12ec..3d57adfc8703 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -24,7 +24,8 @@ 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, AD5273, AD5171, AD5170, AD5172, AD5173 27 ADN2860, AD5273, AD5171, AD5170, AD5172, AD5173, AD5270,
28 AD5271, AD5272, AD5274
28 digital potentiometer chips. 29 digital potentiometer chips.
29 30
30 See Documentation/misc-devices/ad525x_dpot.txt for the 31 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 374352af7979..4ff73c215746 100644
--- a/drivers/misc/ad525x_dpot-i2c.c
+++ b/drivers/misc/ad525x_dpot-i2c.c
@@ -102,6 +102,8 @@ static const struct i2c_device_id ad_dpot_id[] = {
102 {"ad5170", AD5170_ID}, 102 {"ad5170", AD5170_ID},
103 {"ad5172", AD5172_ID}, 103 {"ad5172", AD5172_ID},
104 {"ad5173", AD5173_ID}, 104 {"ad5173", AD5173_ID},
105 {"ad5272", AD5272_ID},
106 {"ad5274", AD5274_ID},
105 {} 107 {}
106}; 108};
107MODULE_DEVICE_TABLE(i2c, ad_dpot_id); 109MODULE_DEVICE_TABLE(i2c, ad_dpot_id);
diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c
index 6cfcb636577a..7f9a55afe05d 100644
--- a/drivers/misc/ad525x_dpot-spi.c
+++ b/drivers/misc/ad525x_dpot-spi.c
@@ -38,6 +38,8 @@ static const struct ad_dpot_id ad_dpot_spi_devlist[] = {
38 {.name = "ad8402", .devid = AD8402_ID}, 38 {.name = "ad8402", .devid = AD8402_ID},
39 {.name = "ad8403", .devid = AD8403_ID}, 39 {.name = "ad8403", .devid = AD8403_ID},
40 {.name = "adn2850", .devid = ADN2850_ID}, 40 {.name = "adn2850", .devid = ADN2850_ID},
41 {.name = "ad5270", .devid = AD5270_ID},
42 {.name = "ad5271", .devid = AD5271_ID},
41 {} 43 {}
42}; 44};
43 45
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c
index 9698c7546911..7cb911028d09 100644
--- a/drivers/misc/ad525x_dpot.c
+++ b/drivers/misc/ad525x_dpot.c
@@ -29,9 +29,9 @@
29 * AD5262 2 256 20, 50, 200 29 * AD5262 2 256 20, 50, 200
30 * AD5263 4 256 20, 50, 200 30 * AD5263 4 256 20, 50, 200
31 * AD5290 1 256 10, 50, 100 31 * AD5290 1 256 10, 50, 100
32 * AD5291 1 256 20 32 * AD5291 1 256 20, 50, 100 (20-TP)
33 * AD5292 1 1024 20 33 * AD5292 1 1024 20, 50, 100 (20-TP)
34 * AD5293 1 1024 20 34 * AD5293 1 1024 20, 50, 100
35 * AD7376 1 128 10, 50, 100, 1M 35 * AD7376 1 128 10, 50, 100, 1M
36 * AD8400 1 256 1, 10, 50, 100 36 * AD8400 1 256 1, 10, 50, 100
37 * AD8402 2 256 1, 10, 50, 100 37 * AD8402 2 256 1, 10, 50, 100
@@ -52,6 +52,10 @@
52 * AD5170 1 256 2.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) 53 * AD5172 2 256 2.5, 10, 50, 100 (OTP)
54 * AD5173 2 256 2.5, 10, 50, 100 (OTP) 54 * AD5173 2 256 2.5, 10, 50, 100 (OTP)
55 * AD5270 1 1024 20, 50, 100 (50-TP)
56 * AD5271 1 256 20, 50, 100 (50-TP)
57 * AD5272 1 1024 20, 50, 100 (50-TP)
58 * AD5274 1 256 20, 50, 100 (50-TP)
55 * 59 *
56 * See Documentation/misc-devices/ad525x_dpot.txt for more info. 60 * See Documentation/misc-devices/ad525x_dpot.txt for more info.
57 * 61 *
@@ -126,18 +130,38 @@ static inline int dpot_write_r8d16(struct dpot_data *dpot, u8 reg, u16 val)
126static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg) 130static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg)
127{ 131{
128 unsigned ctrl = 0; 132 unsigned ctrl = 0;
133 int value;
129 134
130 if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) { 135 if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
131 136
132 if (dpot->feat & F_RDACS_WONLY) 137 if (dpot->feat & F_RDACS_WONLY)
133 return dpot->rdac_cache[reg & DPOT_RDAC_MASK]; 138 return dpot->rdac_cache[reg & DPOT_RDAC_MASK];
134
135 if (dpot->uid == DPOT_UID(AD5291_ID) || 139 if (dpot->uid == DPOT_UID(AD5291_ID) ||
136 dpot->uid == DPOT_UID(AD5292_ID) || 140 dpot->uid == DPOT_UID(AD5292_ID) ||
137 dpot->uid == DPOT_UID(AD5293_ID)) 141 dpot->uid == DPOT_UID(AD5293_ID)) {
138 return dpot_read_r8d8(dpot, 142
143 value = dpot_read_r8d8(dpot,
139 DPOT_AD5291_READ_RDAC << 2); 144 DPOT_AD5291_READ_RDAC << 2);
140 145
146 if (dpot->uid == DPOT_UID(AD5291_ID))
147 value = value >> 2;
148
149 return value;
150 } else if (dpot->uid == DPOT_UID(AD5270_ID) ||
151 dpot->uid == DPOT_UID(AD5271_ID)) {
152
153 value = dpot_read_r8d8(dpot,
154 DPOT_AD5270_1_2_4_READ_RDAC << 2);
155
156 if (value < 0)
157 return value;
158
159 if (dpot->uid == DPOT_UID(AD5271_ID))
160 value = value >> 2;
161
162 return value;
163 }
164
141 ctrl = DPOT_SPI_READ_RDAC; 165 ctrl = DPOT_SPI_READ_RDAC;
142 } else if (reg & DPOT_ADDR_EEPROM) { 166 } else if (reg & DPOT_ADDR_EEPROM) {
143 ctrl = DPOT_SPI_READ_EEPROM; 167 ctrl = DPOT_SPI_READ_EEPROM;
@@ -153,6 +177,7 @@ static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg)
153 177
154static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg) 178static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
155{ 179{
180 int value;
156 unsigned ctrl = 0; 181 unsigned ctrl = 0;
157 switch (dpot->uid) { 182 switch (dpot->uid) {
158 case DPOT_UID(AD5246_ID): 183 case DPOT_UID(AD5246_ID):
@@ -177,6 +202,25 @@ static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
177 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ? 202 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
178 0 : DPOT_AD5172_3_A0; 203 0 : DPOT_AD5172_3_A0;
179 return dpot_read_r8d8(dpot, ctrl); 204 return dpot_read_r8d8(dpot, ctrl);
205 case DPOT_UID(AD5272_ID):
206 case DPOT_UID(AD5274_ID):
207 dpot_write_r8d8(dpot,
208 (DPOT_AD5270_1_2_4_READ_RDAC << 2), 0);
209
210 value = dpot_read_r8d16(dpot,
211 DPOT_AD5270_1_2_4_RDAC << 2);
212
213 if (value < 0)
214 return value;
215 /*
216 * AD5272/AD5274 returns high byte first, however
217 * underling smbus expects low byte first.
218 */
219 value = swab16(value);
220
221 if (dpot->uid == DPOT_UID(AD5271_ID))
222 value = value >> 2;
223 return value;
180 default: 224 default:
181 if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256)) 225 if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256))
182 return dpot_read_r8d16(dpot, (reg & 0xF8) | 226 return dpot_read_r8d16(dpot, (reg & 0xF8) |
@@ -198,7 +242,7 @@ static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
198{ 242{
199 unsigned val = 0; 243 unsigned val = 0;
200 244
201 if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) { 245 if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD | DPOT_ADDR_OTP))) {
202 if (dpot->feat & F_RDACS_WONLY) 246 if (dpot->feat & F_RDACS_WONLY)
203 dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value; 247 dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value;
204 248
@@ -219,11 +263,30 @@ static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
219 } else { 263 } else {
220 if (dpot->uid == DPOT_UID(AD5291_ID) || 264 if (dpot->uid == DPOT_UID(AD5291_ID) ||
221 dpot->uid == DPOT_UID(AD5292_ID) || 265 dpot->uid == DPOT_UID(AD5292_ID) ||
222 dpot->uid == DPOT_UID(AD5293_ID)) 266 dpot->uid == DPOT_UID(AD5293_ID)) {
267
268 dpot_write_r8d8(dpot, DPOT_AD5291_CTRLREG << 2,
269 DPOT_AD5291_UNLOCK_CMD);
270
271 if (dpot->uid == DPOT_UID(AD5291_ID))
272 value = value << 2;
273
223 return dpot_write_r8d8(dpot, 274 return dpot_write_r8d8(dpot,
224 (DPOT_AD5291_RDAC << 2) | 275 (DPOT_AD5291_RDAC << 2) |
225 (value >> 8), value & 0xFF); 276 (value >> 8), value & 0xFF);
277 } else if (dpot->uid == DPOT_UID(AD5270_ID) ||
278 dpot->uid == DPOT_UID(AD5271_ID)) {
279 dpot_write_r8d8(dpot,
280 DPOT_AD5270_1_2_4_CTRLREG << 2,
281 DPOT_AD5270_1_2_4_UNLOCK_CMD);
282
283 if (dpot->uid == DPOT_UID(AD5271_ID))
284 value = value << 2;
226 285
286 return dpot_write_r8d8(dpot,
287 (DPOT_AD5270_1_2_4_RDAC << 2) |
288 (value >> 8), value & 0xFF);
289 }
227 val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK); 290 val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK);
228 } 291 }
229 } else if (reg & DPOT_ADDR_EEPROM) { 292 } else if (reg & DPOT_ADDR_EEPROM) {
@@ -243,6 +306,16 @@ static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
243 val = DPOT_SPI_INC_ALL; 306 val = DPOT_SPI_INC_ALL;
244 break; 307 break;
245 } 308 }
309 } else if (reg & DPOT_ADDR_OTP) {
310 if (dpot->uid == DPOT_UID(AD5291_ID) ||
311 dpot->uid == DPOT_UID(AD5292_ID)) {
312 return dpot_write_r8d8(dpot,
313 DPOT_AD5291_STORE_XTPM << 2, 0);
314 } else if (dpot->uid == DPOT_UID(AD5270_ID) ||
315 dpot->uid == DPOT_UID(AD5271_ID)) {
316 return dpot_write_r8d8(dpot,
317 DPOT_AD5270_1_2_4_STORE_XTPM << 2, 0);
318 }
246 } else 319 } else
247 BUG(); 320 BUG();
248 321
@@ -303,10 +376,25 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
303 tmp = dpot_read_r8d16(dpot, tmp); 376 tmp = dpot_read_r8d16(dpot, tmp);
304 if (tmp >> 14) /* Ready to Program? */ 377 if (tmp >> 14) /* Ready to Program? */
305 return -EFAULT; 378 return -EFAULT;
306 ctrl = DPOT_AD5270_2_3_FUSE; 379 ctrl = DPOT_AD5170_2_3_FUSE;
307 } 380 }
308 return dpot_write_r8d8(dpot, ctrl, value); 381 return dpot_write_r8d8(dpot, ctrl, value);
309 break; 382 break;
383 case DPOT_UID(AD5272_ID):
384 case DPOT_UID(AD5274_ID):
385 dpot_write_r8d8(dpot, DPOT_AD5270_1_2_4_CTRLREG << 2,
386 DPOT_AD5270_1_2_4_UNLOCK_CMD);
387
388 if (reg & DPOT_ADDR_OTP)
389 return dpot_write_r8d8(dpot,
390 DPOT_AD5270_1_2_4_STORE_XTPM << 2, 0);
391
392 if (dpot->uid == DPOT_UID(AD5274_ID))
393 value = value << 2;
394
395 return dpot_write_r8d8(dpot, (DPOT_AD5270_1_2_4_RDAC << 2) |
396 (value >> 8), value & 0xFF);
397 break;
310 default: 398 default:
311 if (reg & DPOT_ADDR_CMD) 399 if (reg & DPOT_ADDR_CMD)
312 return dpot_write_d8(dpot, reg); 400 return dpot_write_d8(dpot, reg);
@@ -320,7 +408,6 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
320 } 408 }
321} 409}
322 410
323
324static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value) 411static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value)
325{ 412{
326 if (dpot->feat & F_SPI) 413 if (dpot->feat & F_SPI)
diff --git a/drivers/misc/ad525x_dpot.h b/drivers/misc/ad525x_dpot.h
index 7609d49efd31..3b9e355489ae 100644
--- a/drivers/misc/ad525x_dpot.h
+++ b/drivers/misc/ad525x_dpot.h
@@ -93,8 +93,10 @@ enum dpot_devid {
93 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 8, 23), 93 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 8, 23),
94 AD5290_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT, 94 AD5290_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
95 BRDAC0, 8, 24), 95 BRDAC0, 8, 24),
96 AD5291_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 8, 25), 96 AD5291_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT | F_CMD_OTP,
97 AD5292_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 26), 97 BRDAC0, 8, 25),
98 AD5292_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT | F_CMD_OTP,
99 BRDAC0, 10, 26),
98 AD5293_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 27), 100 AD5293_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 27),
99 AD7376_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT, 101 AD7376_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
100 BRDAC0, 7, 28), 102 BRDAC0, 7, 28),
@@ -122,6 +124,12 @@ enum dpot_devid {
122 AD5170_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 8, 45), 124 AD5170_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 8, 45),
123 AD5172_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 46), 125 AD5172_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 46),
124 AD5173_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 47), 126 AD5173_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 47),
127 AD5270_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP | F_SPI_16BIT,
128 BRDAC0, 10, 48),
129 AD5271_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP | F_SPI_16BIT,
130 BRDAC0, 8, 49),
131 AD5272_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 10, 50),
132 AD5274_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 8, 51),
125}; 133};
126 134
127#define DPOT_RDAC0 0 135#define DPOT_RDAC0 0
@@ -165,10 +173,19 @@ enum dpot_devid {
165/* AD5291/2/3 use special commands */ 173/* AD5291/2/3 use special commands */
166#define DPOT_AD5291_RDAC 0x01 174#define DPOT_AD5291_RDAC 0x01
167#define DPOT_AD5291_READ_RDAC 0x02 175#define DPOT_AD5291_READ_RDAC 0x02
176#define DPOT_AD5291_STORE_XTPM 0x03
177#define DPOT_AD5291_CTRLREG 0x06
178#define DPOT_AD5291_UNLOCK_CMD 0x03
168 179
169#define DPOT_AD5291_RDAC_AB 0x80 180/* AD5270/1/2/4 use special commands */
181#define DPOT_AD5270_1_2_4_RDAC 0x01
182#define DPOT_AD5270_1_2_4_READ_RDAC 0x02
183#define DPOT_AD5270_1_2_4_STORE_XTPM 0x03
184#define DPOT_AD5270_1_2_4_CTRLREG 0x07
185#define DPOT_AD5270_1_2_4_UNLOCK_CMD 0x03
170 186
171#define DPOT_AD5282_RDAC_AB 0x80 187#define DPOT_AD5282_RDAC_AB 0x80
188
172#define DPOT_AD5273_FUSE 0x80 189#define DPOT_AD5273_FUSE 0x80
173#define DPOT_AD5170_2_3_FUSE 0x20 190#define DPOT_AD5170_2_3_FUSE 0x20
174#define DPOT_AD5170_2_3_OW 0x08 191#define DPOT_AD5170_2_3_OW 0x08