aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
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
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')
-rw-r--r--drivers/misc/Kconfig3
-rw-r--r--drivers/misc/ad525x_dpot-i2c.c7
-rw-r--r--drivers/misc/ad525x_dpot.c234
-rw-r--r--drivers/misc/ad525x_dpot.h27
4 files changed, 175 insertions, 96 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 69e019e7d69c..90c3415dc90a 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -22,7 +22,8 @@ config AD525X_DPOT
22 AD5160, AD5161, AD5162, AD5165, AD5200, AD5201, AD5203, 22 AD5160, AD5161, AD5162, AD5165, AD5200, AD5201, AD5203,
23 AD5204, AD5206, AD5207, AD5231, AD5232, AD5233, AD5235, 23 AD5204, AD5206, AD5207, AD5231, AD5232, AD5233, AD5235,
24 AD5260, AD5262, AD5263, AD5290, AD5291, AD5292, AD5293, 24 AD5260, AD5262, AD5263, AD5290, AD5291, AD5292, AD5293,
25 AD7376, AD8400, AD8402, AD8403, ADN2850 25 AD7376, AD8400, AD8402, AD8403, ADN2850, AD5241, AD5242,
26 AD5243, AD5245, AD5246, AD5247, AD5248
26 digital potentiometer chips. 27 digital potentiometer chips.
27 28
28 See Documentation/misc-devices/ad525x_dpot.txt for the 29 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 971e61d7f881..0dfad4e70f74 100644
--- a/drivers/misc/ad525x_dpot-i2c.c
+++ b/drivers/misc/ad525x_dpot-i2c.c
@@ -87,6 +87,13 @@ static const struct i2c_device_id ad_dpot_id[] = {
87 {"ad5253", AD5253_ID}, 87 {"ad5253", AD5253_ID},
88 {"ad5254", AD5254_ID}, 88 {"ad5254", AD5254_ID},
89 {"ad5255", AD5255_ID}, 89 {"ad5255", AD5255_ID},
90 {"ad5241", AD5241_ID},
91 {"ad5242", AD5242_ID},
92 {"ad5243", AD5243_ID},
93 {"ad5245", AD5245_ID},
94 {"ad5246", AD5246_ID},
95 {"ad5247", AD5247_ID},
96 {"ad5248", AD5248_ID},
90 {} 97 {}
91}; 98};
92MODULE_DEVICE_TABLE(i2c, ad_dpot_id); 99MODULE_DEVICE_TABLE(i2c, ad_dpot_id);
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,
diff --git a/drivers/misc/ad525x_dpot.h b/drivers/misc/ad525x_dpot.h
index 99b388e12f5f..849c5d0782b2 100644
--- a/drivers/misc/ad525x_dpot.h
+++ b/drivers/misc/ad525x_dpot.h
@@ -29,13 +29,14 @@
29 29
30#define F_CMD_INC (1 << 0) /* Features INC/DEC ALL, 6dB */ 30#define F_CMD_INC (1 << 0) /* Features INC/DEC ALL, 6dB */
31#define F_CMD_EEP (1 << 1) /* Features EEPROM */ 31#define F_CMD_EEP (1 << 1) /* Features EEPROM */
32#define F_CMD_TOL (1 << 2) /* RDACS are Read/Write + Tolerance REG */ 32#define F_CMD_OTP (1 << 2) /* Features OTP */
33#define F_RDACS_RW (1 << 3) /* RDACS are Read/Write + Tolerance REG */ 33#define F_CMD_TOL (1 << 3) /* RDACS feature Tolerance REG */
34#define F_RDACS_WONLY (1 << 4) /* RDACS are Write only */ 34#define F_RDACS_RW (1 << 4) /* RDACS are Read/Write */
35#define F_AD_APPDATA (1 << 5) /* RDAC Address append to data */ 35#define F_RDACS_WONLY (1 << 5) /* RDACS are Write only */
36#define F_SPI_8BIT (1 << 6) /* All SPI XFERS are 8-bit */ 36#define F_AD_APPDATA (1 << 6) /* RDAC Address append to data */
37#define F_SPI_16BIT (1 << 7) /* All SPI XFERS are 16-bit */ 37#define F_SPI_8BIT (1 << 7) /* All SPI XFERS are 8-bit */
38#define F_SPI_24BIT (1 << 8) /* All SPI XFERS are 24-bit */ 38#define F_SPI_16BIT (1 << 8) /* All SPI XFERS are 16-bit */
39#define F_SPI_24BIT (1 << 9) /* All SPI XFERS are 24-bit */
39 40
40#define F_RDACS_RW_TOL (F_RDACS_RW | F_CMD_EEP | F_CMD_TOL) 41#define F_RDACS_RW_TOL (F_RDACS_RW | F_CMD_EEP | F_CMD_TOL)
41#define F_RDACS_RW_EEP (F_RDACS_RW | F_CMD_EEP) 42#define F_RDACS_RW_EEP (F_RDACS_RW | F_CMD_EEP)
@@ -104,6 +105,15 @@ enum dpot_devid {
104 BRDAC0 | BRDAC1 | BRDAC2, 8, 31), 105 BRDAC0 | BRDAC1 | BRDAC2, 8, 31),
105 ADN2850_ID = DPOT_CONF(F_RDACS_RW_EEP | F_CMD_INC | F_SPI_24BIT, 106 ADN2850_ID = DPOT_CONF(F_RDACS_RW_EEP | F_CMD_INC | F_SPI_24BIT,
106 BRDAC0 | BRDAC1, 10, 32), 107 BRDAC0 | BRDAC1, 10, 32),
108 AD5241_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 8, 33),
109 AD5242_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 34),
110 AD5243_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 35),
111 AD5245_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 8, 36),
112 AD5246_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 7, 37),
113 AD5247_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 7, 38),
114 AD5248_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 39),
115
116
107}; 117};
108 118
109#define DPOT_RDAC0 0 119#define DPOT_RDAC0 0
@@ -146,6 +156,9 @@ enum dpot_devid {
146#define DPOT_AD5291_RDAC 0x01 156#define DPOT_AD5291_RDAC 0x01
147#define DPOT_AD5291_READ_RDAC 0x02 157#define DPOT_AD5291_READ_RDAC 0x02
148 158
159/* AD524x use special commands */
160#define DPOT_AD5291_RDAC_AB 0x80
161
149struct dpot_data; 162struct dpot_data;
150 163
151struct ad_dpot_bus_ops { 164struct ad_dpot_bus_ops {