aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/ad525x_dpot.c
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2010-05-24 17:33:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-25 11:07:04 -0400
commite3ae68476ce0636554b5d95a33777f80ba407dc0 (patch)
tree3aa1fbefa2d573e1830914fe899f79caf90157d8 /drivers/misc/ad525x_dpot.c
parent6c536e4ce8edd61fdc4ab68e19ae164a54fc958f (diff)
ad525x_dpot: add support for AD524x pots
New parts supported: AD5241, AD5242, AD5243, AD5245, AD5246, AD5247, AD5248 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.c234
1 files changed, 146 insertions, 88 deletions
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c
index a41c2de0eae8..35a4c4b343d4 100644
--- a/drivers/misc/ad525x_dpot.c
+++ b/drivers/misc/ad525x_dpot.c
@@ -37,6 +37,13 @@
37 * AD8402 2 256 1, 10, 50, 100 37 * AD8402 2 256 1, 10, 50, 100
38 * AD8403 4 256 1, 10, 50, 100 38 * AD8403 4 256 1, 10, 50, 100
39 * ADN2850 3 512 25, 250 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
40 * 47 *
41 * See Documentation/misc-devices/ad525x_dpot.txt for more info. 48 * See Documentation/misc-devices/ad525x_dpot.txt for more info.
42 * 49 *
@@ -107,118 +114,169 @@ static inline int dpot_write_r8d16(struct dpot_data *dpot, u8 reg, u16 val)
107 return dpot->bdata.bops->write_r8d16(dpot->bdata.client, reg, val); 114 return dpot->bdata.bops->write_r8d16(dpot->bdata.client, reg, val);
108} 115}
109 116
110static s32 dpot_read(struct dpot_data *dpot, u8 reg) 117static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg)
111{ 118{
112 unsigned val = 0; 119 unsigned ctrl = 0;
113 120
114 if (dpot->feat & F_SPI) { 121 if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
115 if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
116 122
117 if (dpot->feat & F_RDACS_WONLY) 123 if (dpot->feat & F_RDACS_WONLY)
118 return dpot->rdac_cache[reg & DPOT_RDAC_MASK]; 124 return dpot->rdac_cache[reg & DPOT_RDAC_MASK];
119 125
120 if (dpot->uid == DPOT_UID(AD5291_ID) || 126 if (dpot->uid == DPOT_UID(AD5291_ID) ||
121 dpot->uid == DPOT_UID(AD5292_ID) || 127 dpot->uid == DPOT_UID(AD5292_ID) ||
122 dpot->uid == DPOT_UID(AD5293_ID)) 128 dpot->uid == DPOT_UID(AD5293_ID))
123 return dpot_read_r8d8(dpot, 129 return dpot_read_r8d8(dpot,
124 DPOT_AD5291_READ_RDAC << 2); 130 DPOT_AD5291_READ_RDAC << 2);
125 131
126 val = DPOT_SPI_READ_RDAC; 132 ctrl = DPOT_SPI_READ_RDAC;
127 } else if (reg & DPOT_ADDR_EEPROM) { 133 } else if (reg & DPOT_ADDR_EEPROM) {
128 val = DPOT_SPI_READ_EEPROM; 134 ctrl = DPOT_SPI_READ_EEPROM;
129 } 135 }
130 136
131 if (dpot->feat & F_SPI_16BIT) 137 if (dpot->feat & F_SPI_16BIT)
132 return dpot_read_r8d8(dpot, val); 138 return dpot_read_r8d8(dpot, ctrl);
133 else if (dpot->feat & F_SPI_24BIT) 139 else if (dpot->feat & F_SPI_24BIT)
134 return dpot_read_r8d16(dpot, val); 140 return dpot_read_r8d16(dpot, ctrl);
135 141
136 } else { /* I2C */ 142 return -EFAULT;
143}
137 144
145static 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:
138 if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256)) 161 if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256))
139 return dpot_read_r8d16(dpot, (reg & 0xF8) | 162 return dpot_read_r8d16(dpot, (reg & 0xF8) |
140 ((reg & 0x7) << 1)); 163 ((reg & 0x7) << 1));
141 else 164 else
142 return dpot_read_r8d8(dpot, reg); 165 return dpot_read_r8d8(dpot, reg);
143
144 } 166 }
145 return -EFAULT;
146} 167}
147 168
148static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value) 169static 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
177static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
149{ 178{
150 unsigned val = 0; 179 unsigned val = 0;
151 180
152 if (dpot->feat & F_SPI) { 181 if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
153 if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) { 182 if (dpot->feat & F_RDACS_WONLY)
154 if (dpot->feat & F_RDACS_WONLY) 183 dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value;
155 dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value; 184
156 185 if (dpot->feat & F_AD_APPDATA) {
157 if (dpot->feat & F_AD_APPDATA) { 186 if (dpot->feat & F_SPI_8BIT) {
158 if (dpot->feat & F_SPI_8BIT) { 187 val = ((reg & DPOT_RDAC_MASK) <<
159 val = ((reg & DPOT_RDAC_MASK) << 188 DPOT_MAX_POS(dpot->devid)) |
160 DPOT_MAX_POS(dpot->devid)) | 189 value;
161 value; 190 return dpot_write_d8(dpot, val);
162 return dpot_write_d8(dpot, val); 191 } else if (dpot->feat & F_SPI_16BIT) {
163 } else if (dpot->feat & F_SPI_16BIT) { 192 val = ((reg & DPOT_RDAC_MASK) <<
164 val = ((reg & DPOT_RDAC_MASK) << 193 DPOT_MAX_POS(dpot->devid)) |
165 DPOT_MAX_POS(dpot->devid)) | 194 value;
166 value; 195 return dpot_write_r8d8(dpot, val >> 8,
167 return dpot_write_r8d8(dpot, val >> 8, 196 val & 0xFF);
168 val & 0xFF); 197 } else
169 } else 198 BUG();
170 BUG(); 199 } else {
171 } else { 200 if (dpot->uid == DPOT_UID(AD5291_ID) ||
172 if (dpot->uid == DPOT_UID(AD5291_ID) || 201 dpot->uid == DPOT_UID(AD5292_ID) ||
173 dpot->uid == DPOT_UID(AD5292_ID) || 202 dpot->uid == DPOT_UID(AD5293_ID))
174 dpot->uid == DPOT_UID(AD5293_ID)) 203 return dpot_write_r8d8(dpot,
175 return dpot_write_r8d8(dpot, 204 (DPOT_AD5291_RDAC << 2) |
176 (DPOT_AD5291_RDAC << 2) | 205 (value >> 8), value & 0xFF);
177 (value >> 8), value & 0xFF);
178
179 val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK);
180 }
181 } else if (reg & DPOT_ADDR_EEPROM) {
182 val = DPOT_SPI_EEPROM | (reg & DPOT_RDAC_MASK);
183 } else if (reg & DPOT_ADDR_CMD) {
184 switch (reg) {
185 case DPOT_DEC_ALL_6DB:
186 val = DPOT_SPI_DEC_ALL_6DB;
187 break;
188 case DPOT_INC_ALL_6DB:
189 val = DPOT_SPI_INC_ALL_6DB;
190 break;
191 case DPOT_DEC_ALL:
192 val = DPOT_SPI_DEC_ALL;
193 break;
194 case DPOT_INC_ALL:
195 val = DPOT_SPI_INC_ALL;
196 break;
197 }
198 } else
199 BUG();
200
201 if (dpot->feat & F_SPI_16BIT)
202 return dpot_write_r8d8(dpot, val, value);
203 else if (dpot->feat & F_SPI_24BIT)
204 return dpot_write_r8d16(dpot, val, value);
205 } else {
206 /* Only write the instruction byte for certain commands */
207 if (reg & DPOT_ADDR_CMD)
208 return dpot_write_d8(dpot, reg);
209
210 if (dpot->max_pos > 256)
211 return dpot_write_r8d16(dpot, (reg & 0xF8) |
212 ((reg & 0x7) << 1), value);
213 else
214 /* All other registers require instruction + data bytes */
215 return dpot_write_r8d8(dpot, reg, value);
216 206
217 } 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);
218 233
219 return -EFAULT; 234 return -EFAULT;
220} 235}
221 236
237static 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
272static 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
222/* sysfs functions */ 280/* sysfs functions */
223 281
224static ssize_t sysfs_show_reg(struct device *dev, 282static ssize_t sysfs_show_reg(struct device *dev,