diff options
author | Michael Hennerich <michael.hennerich@analog.com> | 2010-10-26 17:22:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-26 19:52:14 -0400 |
commit | a4bd394956f20d0bfc0ca6ecfac2af4150da274a (patch) | |
tree | 5513a0ad4c7cedeb98fc0c521ff13d39752e729d /drivers/misc/ad525x_dpot.c | |
parent | 5f400cf40fc703673aa791966ffb1c628c1ff45a (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/ad525x_dpot.c')
-rw-r--r-- | drivers/misc/ad525x_dpot.c | 107 |
1 files changed, 97 insertions, 10 deletions
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) | |||
126 | static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg) | 130 | static 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 | ||
154 | static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg) | 178 | static 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 | |||
324 | static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value) | 411 | static 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) |