Blame view

drivers/misc/ad525x_dpot.c 20.1 KB
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
1
  /*
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
2
3
   * ad525x_dpot: Driver for the Analog Devices digital potentiometers
   * Copyright (c) 2009-2010 Analog Devices, Inc.
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
4
5
6
7
8
9
10
11
12
13
   * Author: Michael Hennerich <hennerich@blackfin.uclinux.org>
   *
   * DEVID		#Wipers		#Positions 	Resistor Options (kOhm)
   * AD5258		1		64		1, 10, 50, 100
   * AD5259		1		256		5, 10, 50, 100
   * AD5251		2		64		1, 10, 50, 100
   * AD5252		2		256		1, 10, 50, 100
   * AD5255		3		512		25, 250
   * AD5253		4		64		1, 10, 50, 100
   * AD5254		4		256		1, 10, 50, 100
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
   * AD5160		1		256		5, 10, 50, 100
   * AD5161		1		256		5, 10, 50, 100
   * AD5162		2		256		2.5, 10, 50, 100
   * AD5165		1		256		100
   * AD5200		1		256		10, 50
   * AD5201		1		33		10, 50
   * AD5203		4		64		10, 100
   * AD5204		4		256		10, 50, 100
   * AD5206		6		256		10, 50, 100
   * AD5207		2		256		10, 50, 100
   * AD5231		1		1024		10, 50, 100
   * AD5232		2		256		10, 50, 100
   * AD5233		4		64		10, 50, 100
   * AD5235		2		1024		25, 250
   * AD5260		1		256		20, 50, 200
   * AD5262		2		256		20, 50, 200
   * AD5263		4		256		20, 50, 200
   * AD5290		1		256		10, 50, 100
a4bd39495   Michael Hennerich   drivers/misc/ad52...
32
33
34
   * AD5291		1		256		20, 50, 100  (20-TP)
   * AD5292		1		1024		20, 50, 100  (20-TP)
   * AD5293		1		1024		20, 50, 100
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
35
36
37
38
39
   * AD7376		1		128		10, 50, 100, 1M
   * AD8400		1		256		1, 10, 50, 100
   * AD8402		2		256		1, 10, 50, 100
   * AD8403		4		256		1, 10, 50, 100
   * ADN2850		3		512		25, 250
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
40
41
42
43
44
45
46
   * AD5241		1		256		10, 100, 1M
   * AD5246		1		128		5, 10, 50, 100
   * AD5247		1		128		5, 10, 50, 100
   * AD5245		1		256		5, 10, 50, 100
   * AD5243		2		256		2.5, 10, 50, 100
   * AD5248		2		256		2.5, 10, 50, 100
   * AD5242		2		256		20, 50, 200
c74cba610   Michael Hennerich   ad525x_dpot: add ...
47
48
49
   * AD5280		1		256		20, 50, 200
   * AD5282		2		256		20, 50, 200
   * ADN2860		3		512		25, 250
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
50
51
52
53
54
   * AD5273		1		64		1, 10, 50, 100 (OTP)
   * AD5171		1		64		5, 10, 50, 100 (OTP)
   * AD5170		1		256		2.5, 10, 50, 100 (OTP)
   * AD5172		2		256		2.5, 10, 50, 100 (OTP)
   * AD5173		2		256		2.5, 10, 50, 100 (OTP)
a4bd39495   Michael Hennerich   drivers/misc/ad52...
55
56
57
58
   * AD5270		1		1024		20, 50, 100 (50-TP)
   * AD5271		1		256		20, 50, 100 (50-TP)
   * AD5272		1		1024		20, 50, 100 (50-TP)
   * AD5274		1		256		20, 50, 100 (50-TP)
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
59
60
61
62
63
64
65
66
   *
   * See Documentation/misc-devices/ad525x_dpot.txt for more info.
   *
   * derived from ad5258.c
   * Copyright (c) 2009 Cyber Switching, Inc.
   * Author: Chris Verges <chrisv@cyberswitching.com>
   *
   * derived from ad5252.c
7f3379de9   Michael Hennerich   misc: ad525x_dpot...
67
   * Copyright (c) 2006-2011 Michael Hennerich <hennerich@blackfin.uclinux.org>
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
68
69
70
71
72
73
74
   *
   * Licensed under the GPL-2 or later.
   */
  
  #include <linux/module.h>
  #include <linux/device.h>
  #include <linux/kernel.h>
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
75
  #include <linux/delay.h>
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
76
  #include <linux/slab.h>
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
77

6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
78
  #include "ad525x_dpot.h"
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
79
80
81
82
83
84
  
  /*
   * Client data (each client gets its own)
   */
  
  struct dpot_data {
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
85
  	struct ad_dpot_bus_data	bdata;
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
86
87
88
  	struct mutex update_lock;
  	unsigned rdac_mask;
  	unsigned max_pos;
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
89
90
91
92
  	unsigned long devid;
  	unsigned uid;
  	unsigned feat;
  	unsigned wipers;
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
93
94
  	u16 rdac_cache[MAX_RDACS];
  	DECLARE_BITMAP(otp_en_mask, MAX_RDACS);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
95
  };
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
  static inline int dpot_read_d8(struct dpot_data *dpot)
  {
  	return dpot->bdata.bops->read_d8(dpot->bdata.client);
  }
  
  static inline int dpot_read_r8d8(struct dpot_data *dpot, u8 reg)
  {
  	return dpot->bdata.bops->read_r8d8(dpot->bdata.client, reg);
  }
  
  static inline int dpot_read_r8d16(struct dpot_data *dpot, u8 reg)
  {
  	return dpot->bdata.bops->read_r8d16(dpot->bdata.client, reg);
  }
  
  static inline int dpot_write_d8(struct dpot_data *dpot, u8 val)
  {
  	return dpot->bdata.bops->write_d8(dpot->bdata.client, val);
  }
  
  static inline int dpot_write_r8d8(struct dpot_data *dpot, u8 reg, u16 val)
  {
  	return dpot->bdata.bops->write_r8d8(dpot->bdata.client, reg, val);
  }
  
  static inline int dpot_write_r8d16(struct dpot_data *dpot, u8 reg, u16 val)
  {
  	return dpot->bdata.bops->write_r8d16(dpot->bdata.client, reg, val);
  }
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
125
  static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg)
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
126
  {
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
127
  	unsigned ctrl = 0;
a4bd39495   Michael Hennerich   drivers/misc/ad52...
128
  	int value;
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
129

e3ae68476   Michael Hennerich   ad525x_dpot: add ...
130
  	if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
131

e3ae68476   Michael Hennerich   ad525x_dpot: add ...
132
133
  		if (dpot->feat & F_RDACS_WONLY)
  			return dpot->rdac_cache[reg & DPOT_RDAC_MASK];
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
134
135
  		if (dpot->uid == DPOT_UID(AD5291_ID) ||
  			dpot->uid == DPOT_UID(AD5292_ID) ||
a4bd39495   Michael Hennerich   drivers/misc/ad52...
136
137
138
  			dpot->uid == DPOT_UID(AD5293_ID)) {
  
  			value = dpot_read_r8d8(dpot,
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
139
  				DPOT_AD5291_READ_RDAC << 2);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
140

a4bd39495   Michael Hennerich   drivers/misc/ad52...
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  			if (dpot->uid == DPOT_UID(AD5291_ID))
  				value = value >> 2;
  
  			return value;
  		} else if (dpot->uid == DPOT_UID(AD5270_ID) ||
  			dpot->uid == DPOT_UID(AD5271_ID)) {
  
  			value = dpot_read_r8d8(dpot,
  				DPOT_AD5270_1_2_4_READ_RDAC << 2);
  
  			if (value < 0)
  				return value;
  
  			if (dpot->uid == DPOT_UID(AD5271_ID))
  				value = value >> 2;
  
  			return value;
  		}
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
159
160
161
162
  		ctrl = DPOT_SPI_READ_RDAC;
  	} else if (reg & DPOT_ADDR_EEPROM) {
  		ctrl = DPOT_SPI_READ_EEPROM;
  	}
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
163

e3ae68476   Michael Hennerich   ad525x_dpot: add ...
164
165
166
167
  	if (dpot->feat & F_SPI_16BIT)
  		return dpot_read_r8d8(dpot, ctrl);
  	else if (dpot->feat & F_SPI_24BIT)
  		return dpot_read_r8d16(dpot, ctrl);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
168

e3ae68476   Michael Hennerich   ad525x_dpot: add ...
169
170
  	return -EFAULT;
  }
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
171

e3ae68476   Michael Hennerich   ad525x_dpot: add ...
172
173
  static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
  {
a4bd39495   Michael Hennerich   drivers/misc/ad52...
174
  	int value;
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
175
  	unsigned ctrl = 0;
155845558   Mohammad Jamal   ad525x_dpot: Add ...
176

e3ae68476   Michael Hennerich   ad525x_dpot: add ...
177
178
179
180
181
182
183
184
185
  	switch (dpot->uid) {
  	case DPOT_UID(AD5246_ID):
  	case DPOT_UID(AD5247_ID):
  		return dpot_read_d8(dpot);
  	case DPOT_UID(AD5245_ID):
  	case DPOT_UID(AD5241_ID):
  	case DPOT_UID(AD5242_ID):
  	case DPOT_UID(AD5243_ID):
  	case DPOT_UID(AD5248_ID):
c74cba610   Michael Hennerich   ad525x_dpot: add ...
186
187
  	case DPOT_UID(AD5280_ID):
  	case DPOT_UID(AD5282_ID):
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
188
  		ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
5f400cf40   Michael Hennerich   drivers/misc/ad52...
189
  			0 : DPOT_AD5282_RDAC_AB;
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
190
  		return dpot_read_r8d8(dpot, ctrl);
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
191
192
193
194
195
196
197
  	case DPOT_UID(AD5170_ID):
  	case DPOT_UID(AD5171_ID):
  	case DPOT_UID(AD5273_ID):
  			return dpot_read_d8(dpot);
  	case DPOT_UID(AD5172_ID):
  	case DPOT_UID(AD5173_ID):
  		ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
5f400cf40   Michael Hennerich   drivers/misc/ad52...
198
  			0 : DPOT_AD5172_3_A0;
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
199
  		return dpot_read_r8d8(dpot, ctrl);
a4bd39495   Michael Hennerich   drivers/misc/ad52...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  	case DPOT_UID(AD5272_ID):
  	case DPOT_UID(AD5274_ID):
  			dpot_write_r8d8(dpot,
  				(DPOT_AD5270_1_2_4_READ_RDAC << 2), 0);
  
  			value = dpot_read_r8d16(dpot,
  				DPOT_AD5270_1_2_4_RDAC << 2);
  
  			if (value < 0)
  				return value;
  			/*
  			 * AD5272/AD5274 returns high byte first, however
  			 * underling smbus expects low byte first.
  			 */
  			value = swab16(value);
f3df53e4d   Michael Hennerich   drivers/misc/ad52...
215
  			if (dpot->uid == DPOT_UID(AD5274_ID))
a4bd39495   Michael Hennerich   drivers/misc/ad52...
216
217
  				value = value >> 2;
  		return value;
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
218
  	default:
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
219
220
221
222
223
  		if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256))
  			return dpot_read_r8d16(dpot, (reg & 0xF8) |
  					((reg & 0x7) << 1));
  		else
  			return dpot_read_r8d8(dpot, reg);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
224
  	}
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
225
  }
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
226
227
228
229
230
231
232
233
234
  static s32 dpot_read(struct dpot_data *dpot, u8 reg)
  {
  	if (dpot->feat & F_SPI)
  		return dpot_read_spi(dpot, reg);
  	else
  		return dpot_read_i2c(dpot, reg);
  }
  
  static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
235
236
  {
  	unsigned val = 0;
a4bd39495   Michael Hennerich   drivers/misc/ad52...
237
  	if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD | DPOT_ADDR_OTP))) {
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
  		if (dpot->feat & F_RDACS_WONLY)
  			dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value;
  
  		if (dpot->feat & F_AD_APPDATA) {
  			if (dpot->feat & F_SPI_8BIT) {
  				val = ((reg & DPOT_RDAC_MASK) <<
  					DPOT_MAX_POS(dpot->devid)) |
  					value;
  				return dpot_write_d8(dpot, val);
  			} else if (dpot->feat & F_SPI_16BIT) {
  				val = ((reg & DPOT_RDAC_MASK) <<
  					DPOT_MAX_POS(dpot->devid)) |
  					value;
  				return dpot_write_r8d8(dpot, val >> 8,
  					val & 0xFF);
  			} else
  				BUG();
  		} else {
  			if (dpot->uid == DPOT_UID(AD5291_ID) ||
  				dpot->uid == DPOT_UID(AD5292_ID) ||
a4bd39495   Michael Hennerich   drivers/misc/ad52...
258
259
260
261
262
263
264
  				dpot->uid == DPOT_UID(AD5293_ID)) {
  
  				dpot_write_r8d8(dpot, DPOT_AD5291_CTRLREG << 2,
  						DPOT_AD5291_UNLOCK_CMD);
  
  				if (dpot->uid == DPOT_UID(AD5291_ID))
  					value = value << 2;
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
265
266
267
  				return dpot_write_r8d8(dpot,
  					(DPOT_AD5291_RDAC << 2) |
  					(value >> 8), value & 0xFF);
a4bd39495   Michael Hennerich   drivers/misc/ad52...
268
269
270
271
272
273
274
275
  			} else if (dpot->uid == DPOT_UID(AD5270_ID) ||
  				dpot->uid == DPOT_UID(AD5271_ID)) {
  				dpot_write_r8d8(dpot,
  						DPOT_AD5270_1_2_4_CTRLREG << 2,
  						DPOT_AD5270_1_2_4_UNLOCK_CMD);
  
  				if (dpot->uid == DPOT_UID(AD5271_ID))
  					value = value << 2;
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
276

a4bd39495   Michael Hennerich   drivers/misc/ad52...
277
278
279
280
  				return dpot_write_r8d8(dpot,
  					(DPOT_AD5270_1_2_4_RDAC << 2) |
  					(value >> 8), value & 0xFF);
  			}
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
  			val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK);
  		}
  	} else if (reg & DPOT_ADDR_EEPROM) {
  		val = DPOT_SPI_EEPROM | (reg & DPOT_RDAC_MASK);
  	} else if (reg & DPOT_ADDR_CMD) {
  		switch (reg) {
  		case DPOT_DEC_ALL_6DB:
  			val = DPOT_SPI_DEC_ALL_6DB;
  			break;
  		case DPOT_INC_ALL_6DB:
  			val = DPOT_SPI_INC_ALL_6DB;
  			break;
  		case DPOT_DEC_ALL:
  			val = DPOT_SPI_DEC_ALL;
  			break;
  		case DPOT_INC_ALL:
  			val = DPOT_SPI_INC_ALL;
  			break;
  		}
a4bd39495   Michael Hennerich   drivers/misc/ad52...
300
301
302
303
304
305
306
307
308
309
  	} else if (reg & DPOT_ADDR_OTP) {
  		if (dpot->uid == DPOT_UID(AD5291_ID) ||
  			dpot->uid == DPOT_UID(AD5292_ID)) {
  			return dpot_write_r8d8(dpot,
  				DPOT_AD5291_STORE_XTPM << 2, 0);
  		} else if (dpot->uid == DPOT_UID(AD5270_ID) ||
  			dpot->uid == DPOT_UID(AD5271_ID)) {
  			return dpot_write_r8d8(dpot,
  				DPOT_AD5270_1_2_4_STORE_XTPM << 2, 0);
  		}
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
310
311
312
313
314
315
316
  	} else
  		BUG();
  
  	if (dpot->feat & F_SPI_16BIT)
  		return dpot_write_r8d8(dpot, val, value);
  	else if (dpot->feat & F_SPI_24BIT)
  		return dpot_write_r8d16(dpot, val, value);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
317
318
319
  
  	return -EFAULT;
  }
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
320
321
322
  static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
  {
  	/* Only write the instruction byte for certain commands */
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
323
  	unsigned tmp = 0, ctrl = 0;
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
324
325
326
327
328
  
  	switch (dpot->uid) {
  	case DPOT_UID(AD5246_ID):
  	case DPOT_UID(AD5247_ID):
  		return dpot_write_d8(dpot, value);
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
329
330
331
332
333
334
  
  	case DPOT_UID(AD5245_ID):
  	case DPOT_UID(AD5241_ID):
  	case DPOT_UID(AD5242_ID):
  	case DPOT_UID(AD5243_ID):
  	case DPOT_UID(AD5248_ID):
c74cba610   Michael Hennerich   ad525x_dpot: add ...
335
336
337
  	case DPOT_UID(AD5280_ID):
  	case DPOT_UID(AD5282_ID):
  		ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
5f400cf40   Michael Hennerich   drivers/misc/ad52...
338
  			0 : DPOT_AD5282_RDAC_AB;
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
339
  		return dpot_write_r8d8(dpot, ctrl, value);
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
340
341
342
343
344
345
346
347
348
  	case DPOT_UID(AD5171_ID):
  	case DPOT_UID(AD5273_ID):
  		if (reg & DPOT_ADDR_OTP) {
  			tmp = dpot_read_d8(dpot);
  			if (tmp >> 6) /* Ready to Program? */
  				return -EFAULT;
  			ctrl = DPOT_AD5273_FUSE;
  		}
  		return dpot_write_r8d8(dpot, ctrl, value);
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
349
350
351
  	case DPOT_UID(AD5172_ID):
  	case DPOT_UID(AD5173_ID):
  		ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
5f400cf40   Michael Hennerich   drivers/misc/ad52...
352
  			0 : DPOT_AD5172_3_A0;
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
353
354
355
356
  		if (reg & DPOT_ADDR_OTP) {
  			tmp = dpot_read_r8d16(dpot, ctrl);
  			if (tmp >> 14) /* Ready to Program? */
  				return -EFAULT;
5f400cf40   Michael Hennerich   drivers/misc/ad52...
357
  			ctrl |= DPOT_AD5170_2_3_FUSE;
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
358
359
  		}
  		return dpot_write_r8d8(dpot, ctrl, value);
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
360
361
362
363
364
  	case DPOT_UID(AD5170_ID):
  		if (reg & DPOT_ADDR_OTP) {
  			tmp = dpot_read_r8d16(dpot, tmp);
  			if (tmp >> 14) /* Ready to Program? */
  				return -EFAULT;
a4bd39495   Michael Hennerich   drivers/misc/ad52...
365
  			ctrl = DPOT_AD5170_2_3_FUSE;
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
366
367
  		}
  		return dpot_write_r8d8(dpot, ctrl, value);
a4bd39495   Michael Hennerich   drivers/misc/ad52...
368
369
370
371
372
373
374
375
376
377
378
379
380
381
  	case DPOT_UID(AD5272_ID):
  	case DPOT_UID(AD5274_ID):
  		dpot_write_r8d8(dpot, DPOT_AD5270_1_2_4_CTRLREG << 2,
  				DPOT_AD5270_1_2_4_UNLOCK_CMD);
  
  		if (reg & DPOT_ADDR_OTP)
  			return dpot_write_r8d8(dpot,
  					DPOT_AD5270_1_2_4_STORE_XTPM << 2, 0);
  
  		if (dpot->uid == DPOT_UID(AD5274_ID))
  			value = value << 2;
  
  		return dpot_write_r8d8(dpot, (DPOT_AD5270_1_2_4_RDAC << 2) |
  				       (value >> 8), value & 0xFF);
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
382
  	default:
c74cba610   Michael Hennerich   ad525x_dpot: add ...
383
384
  		if (reg & DPOT_ADDR_CMD)
  			return dpot_write_d8(dpot, reg);
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
385

c74cba610   Michael Hennerich   ad525x_dpot: add ...
386
387
388
389
390
391
  		if (dpot->max_pos > 256)
  			return dpot_write_r8d16(dpot, (reg & 0xF8) |
  						((reg & 0x7) << 1), value);
  		else
  			/* All other registers require instruction + data bytes */
  			return dpot_write_r8d8(dpot, reg, value);
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
392
393
  	}
  }
e3ae68476   Michael Hennerich   ad525x_dpot: add ...
394
395
396
397
398
399
400
  static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value)
  {
  	if (dpot->feat & F_SPI)
  		return dpot_write_spi(dpot, reg, value);
  	else
  		return dpot_write_i2c(dpot, reg, value);
  }
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
401
402
403
  /* sysfs functions */
  
  static ssize_t sysfs_show_reg(struct device *dev,
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
404
405
  			      struct device_attribute *attr,
  			      char *buf, u32 reg)
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
406
  {
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
407
  	struct dpot_data *data = dev_get_drvdata(dev);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
408
  	s32 value;
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
409
410
411
412
413
  	if (reg & DPOT_ADDR_OTP_EN)
  		return sprintf(buf, "%s
  ",
  			test_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask) ?
  			"enabled" : "disabled");
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
414
  	mutex_lock(&data->update_lock);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
415
  	value = dpot_read(data, reg);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
416
417
418
419
420
421
422
423
424
425
426
  	mutex_unlock(&data->update_lock);
  
  	if (value < 0)
  		return -EINVAL;
  	/*
  	 * Let someone else deal with converting this ...
  	 * the tolerance is a two-byte value where the MSB
  	 * is a sign + integer value, and the LSB is a
  	 * decimal value.  See page 18 of the AD5258
  	 * datasheet (Rev. A) for more details.
  	 */
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
427
  	if (reg & DPOT_REG_TOL)
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
428
429
430
431
432
433
434
435
436
437
438
  		return sprintf(buf, "0x%04x
  ", value & 0xFFFF);
  	else
  		return sprintf(buf, "%u
  ", value & data->rdac_mask);
  }
  
  static ssize_t sysfs_set_reg(struct device *dev,
  			     struct device_attribute *attr,
  			     const char *buf, size_t count, u32 reg)
  {
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
439
  	struct dpot_data *data = dev_get_drvdata(dev);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
440
441
  	unsigned long value;
  	int err;
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
442
  	if (reg & DPOT_ADDR_OTP_EN) {
1bb850a1b   Dan Bogdan Nechita   misc: ad525x_dpot...
443
  		if (sysfs_streq(buf, "enabled"))
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
444
445
446
447
448
449
450
451
452
453
  			set_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask);
  		else
  			clear_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask);
  
  		return count;
  	}
  
  	if ((reg & DPOT_ADDR_OTP) &&
  		!test_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask))
  		return -EPERM;
f7b41276b   Jingoo Han   misc: replace str...
454
  	err = kstrtoul(buf, 10, &value);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
455
456
457
458
459
460
461
  	if (err)
  		return err;
  
  	if (value > data->rdac_mask)
  		value = data->rdac_mask;
  
  	mutex_lock(&data->update_lock);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
462
463
  	dpot_write(data, reg, value);
  	if (reg & DPOT_ADDR_EEPROM)
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
464
  		msleep(26);	/* Sleep while the EEPROM updates */
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
465
466
  	else if (reg & DPOT_ADDR_OTP)
  		msleep(400);	/* Sleep while the OTP updates */
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
467
468
469
470
471
472
473
474
475
  	mutex_unlock(&data->update_lock);
  
  	return count;
  }
  
  static ssize_t sysfs_do_cmd(struct device *dev,
  			    struct device_attribute *attr,
  			    const char *buf, size_t count, u32 reg)
  {
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
476
  	struct dpot_data *data = dev_get_drvdata(dev);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
477
478
  
  	mutex_lock(&data->update_lock);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
479
  	dpot_write(data, reg, 0);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
480
481
482
483
484
485
  	mutex_unlock(&data->update_lock);
  
  	return count;
  }
  
  /* ------------------------------------------------------------------------- */
0993dbedf   Michael Hennerich   ad525x_dpot: simp...
486
487
488
489
490
  #define DPOT_DEVICE_SHOW(_name, _reg) static ssize_t \
  show_##_name(struct device *dev, \
  			  struct device_attribute *attr, char *buf) \
  { \
  	return sysfs_show_reg(dev, attr, buf, _reg); \
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
491
  }
0993dbedf   Michael Hennerich   ad525x_dpot: simp...
492
493
494
495
496
497
  #define DPOT_DEVICE_SET(_name, _reg) static ssize_t \
  set_##_name(struct device *dev, \
  			 struct device_attribute *attr, \
  			 const char *buf, size_t count) \
  { \
  	return sysfs_set_reg(dev, attr, buf, count, _reg); \
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
498
  }
0993dbedf   Michael Hennerich   ad525x_dpot: simp...
499
500
501
502
  #define DPOT_DEVICE_SHOW_SET(name, reg) \
  DPOT_DEVICE_SHOW(name, reg) \
  DPOT_DEVICE_SET(name, reg) \
  static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, show_##name, set_##name);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
503

0993dbedf   Michael Hennerich   ad525x_dpot: simp...
504
505
506
  #define DPOT_DEVICE_SHOW_ONLY(name, reg) \
  DPOT_DEVICE_SHOW(name, reg) \
  static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, show_##name, NULL);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
507

6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
508
509
510
  DPOT_DEVICE_SHOW_SET(rdac0, DPOT_ADDR_RDAC | DPOT_RDAC0);
  DPOT_DEVICE_SHOW_SET(eeprom0, DPOT_ADDR_EEPROM | DPOT_RDAC0);
  DPOT_DEVICE_SHOW_ONLY(tolerance0, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC0);
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
511
512
  DPOT_DEVICE_SHOW_SET(otp0, DPOT_ADDR_OTP | DPOT_RDAC0);
  DPOT_DEVICE_SHOW_SET(otp0en, DPOT_ADDR_OTP_EN | DPOT_RDAC0);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
513
514
515
516
  
  DPOT_DEVICE_SHOW_SET(rdac1, DPOT_ADDR_RDAC | DPOT_RDAC1);
  DPOT_DEVICE_SHOW_SET(eeprom1, DPOT_ADDR_EEPROM | DPOT_RDAC1);
  DPOT_DEVICE_SHOW_ONLY(tolerance1, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC1);
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
517
518
  DPOT_DEVICE_SHOW_SET(otp1, DPOT_ADDR_OTP | DPOT_RDAC1);
  DPOT_DEVICE_SHOW_SET(otp1en, DPOT_ADDR_OTP_EN | DPOT_RDAC1);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
519
520
521
522
  
  DPOT_DEVICE_SHOW_SET(rdac2, DPOT_ADDR_RDAC | DPOT_RDAC2);
  DPOT_DEVICE_SHOW_SET(eeprom2, DPOT_ADDR_EEPROM | DPOT_RDAC2);
  DPOT_DEVICE_SHOW_ONLY(tolerance2, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC2);
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
523
524
  DPOT_DEVICE_SHOW_SET(otp2, DPOT_ADDR_OTP | DPOT_RDAC2);
  DPOT_DEVICE_SHOW_SET(otp2en, DPOT_ADDR_OTP_EN | DPOT_RDAC2);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
525
526
527
528
  
  DPOT_DEVICE_SHOW_SET(rdac3, DPOT_ADDR_RDAC | DPOT_RDAC3);
  DPOT_DEVICE_SHOW_SET(eeprom3, DPOT_ADDR_EEPROM | DPOT_RDAC3);
  DPOT_DEVICE_SHOW_ONLY(tolerance3, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC3);
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
529
530
  DPOT_DEVICE_SHOW_SET(otp3, DPOT_ADDR_OTP | DPOT_RDAC3);
  DPOT_DEVICE_SHOW_SET(otp3en, DPOT_ADDR_OTP_EN | DPOT_RDAC3);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
531
532
533
534
  
  DPOT_DEVICE_SHOW_SET(rdac4, DPOT_ADDR_RDAC | DPOT_RDAC4);
  DPOT_DEVICE_SHOW_SET(eeprom4, DPOT_ADDR_EEPROM | DPOT_RDAC4);
  DPOT_DEVICE_SHOW_ONLY(tolerance4, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC4);
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
535
536
  DPOT_DEVICE_SHOW_SET(otp4, DPOT_ADDR_OTP | DPOT_RDAC4);
  DPOT_DEVICE_SHOW_SET(otp4en, DPOT_ADDR_OTP_EN | DPOT_RDAC4);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
537
538
539
540
  
  DPOT_DEVICE_SHOW_SET(rdac5, DPOT_ADDR_RDAC | DPOT_RDAC5);
  DPOT_DEVICE_SHOW_SET(eeprom5, DPOT_ADDR_EEPROM | DPOT_RDAC5);
  DPOT_DEVICE_SHOW_ONLY(tolerance5, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC5);
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
541
542
  DPOT_DEVICE_SHOW_SET(otp5, DPOT_ADDR_OTP | DPOT_RDAC5);
  DPOT_DEVICE_SHOW_SET(otp5en, DPOT_ADDR_OTP_EN | DPOT_RDAC5);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
  
  static const struct attribute *dpot_attrib_wipers[] = {
  	&dev_attr_rdac0.attr,
  	&dev_attr_rdac1.attr,
  	&dev_attr_rdac2.attr,
  	&dev_attr_rdac3.attr,
  	&dev_attr_rdac4.attr,
  	&dev_attr_rdac5.attr,
  	NULL
  };
  
  static const struct attribute *dpot_attrib_eeprom[] = {
  	&dev_attr_eeprom0.attr,
  	&dev_attr_eeprom1.attr,
  	&dev_attr_eeprom2.attr,
  	&dev_attr_eeprom3.attr,
  	&dev_attr_eeprom4.attr,
  	&dev_attr_eeprom5.attr,
  	NULL
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
562
  };
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
  static const struct attribute *dpot_attrib_otp[] = {
  	&dev_attr_otp0.attr,
  	&dev_attr_otp1.attr,
  	&dev_attr_otp2.attr,
  	&dev_attr_otp3.attr,
  	&dev_attr_otp4.attr,
  	&dev_attr_otp5.attr,
  	NULL
  };
  
  static const struct attribute *dpot_attrib_otp_en[] = {
  	&dev_attr_otp0en.attr,
  	&dev_attr_otp1en.attr,
  	&dev_attr_otp2en.attr,
  	&dev_attr_otp3en.attr,
  	&dev_attr_otp4en.attr,
  	&dev_attr_otp5en.attr,
  	NULL
  };
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
582
583
584
585
586
587
588
589
  static const struct attribute *dpot_attrib_tolerance[] = {
  	&dev_attr_tolerance0.attr,
  	&dev_attr_tolerance1.attr,
  	&dev_attr_tolerance2.attr,
  	&dev_attr_tolerance3.attr,
  	&dev_attr_tolerance4.attr,
  	&dev_attr_tolerance5.attr,
  	NULL
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
590
591
592
  };
  
  /* ------------------------------------------------------------------------- */
0993dbedf   Michael Hennerich   ad525x_dpot: simp...
593
594
595
596
597
598
599
600
  #define DPOT_DEVICE_DO_CMD(_name, _cmd) static ssize_t \
  set_##_name(struct device *dev, \
  			 struct device_attribute *attr, \
  			 const char *buf, size_t count) \
  { \
  	return sysfs_do_cmd(dev, attr, buf, count, _cmd); \
  } \
  static DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, NULL, set_##_name);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
601
602
603
604
  DPOT_DEVICE_DO_CMD(inc_all, DPOT_INC_ALL);
  DPOT_DEVICE_DO_CMD(dec_all, DPOT_DEC_ALL);
  DPOT_DEVICE_DO_CMD(inc_all_6db, DPOT_INC_ALL_6DB);
  DPOT_DEVICE_DO_CMD(dec_all_6db, DPOT_DEC_ALL_6DB);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
605
606
607
608
609
610
611
612
613
614
615
616
  
  static struct attribute *ad525x_attributes_commands[] = {
  	&dev_attr_inc_all.attr,
  	&dev_attr_dec_all.attr,
  	&dev_attr_inc_all_6db.attr,
  	&dev_attr_dec_all_6db.attr,
  	NULL
  };
  
  static const struct attribute_group ad525x_group_commands = {
  	.attrs = ad525x_attributes_commands,
  };
1bdd2c45c   Rashika Kheria   drivers: misc: Ma...
617
  static int ad_dpot_add_files(struct device *dev,
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
618
  		unsigned features, unsigned rdac)
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
619
  {
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
620
621
622
623
624
625
626
627
  	int err = sysfs_create_file(&dev->kobj,
  		dpot_attrib_wipers[rdac]);
  	if (features & F_CMD_EEP)
  		err |= sysfs_create_file(&dev->kobj,
  			dpot_attrib_eeprom[rdac]);
  	if (features & F_CMD_TOL)
  		err |= sysfs_create_file(&dev->kobj,
  			dpot_attrib_tolerance[rdac]);
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
628
629
630
631
632
633
  	if (features & F_CMD_OTP) {
  		err |= sysfs_create_file(&dev->kobj,
  			dpot_attrib_otp_en[rdac]);
  		err |= sysfs_create_file(&dev->kobj,
  			dpot_attrib_otp[rdac]);
  	}
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
634

6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
635
636
637
638
639
640
  	if (err)
  		dev_err(dev, "failed to register sysfs hooks for RDAC%d
  ",
  			rdac);
  
  	return err;
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
641
  }
1bdd2c45c   Rashika Kheria   drivers: misc: Ma...
642
  static inline void ad_dpot_remove_files(struct device *dev,
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
643
  		unsigned features, unsigned rdac)
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
644
  {
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
645
646
647
648
649
650
651
652
  	sysfs_remove_file(&dev->kobj,
  		dpot_attrib_wipers[rdac]);
  	if (features & F_CMD_EEP)
  		sysfs_remove_file(&dev->kobj,
  			dpot_attrib_eeprom[rdac]);
  	if (features & F_CMD_TOL)
  		sysfs_remove_file(&dev->kobj,
  			dpot_attrib_tolerance[rdac]);
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
653
654
655
656
657
658
  	if (features & F_CMD_OTP) {
  		sysfs_remove_file(&dev->kobj,
  			dpot_attrib_otp_en[rdac]);
  		sysfs_remove_file(&dev->kobj,
  			dpot_attrib_otp[rdac]);
  	}
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
659
  }
80c8ae289   Bill Pemberton   misc: remove use ...
660
  int ad_dpot_probe(struct device *dev,
7f3379de9   Michael Hennerich   misc: ad525x_dpot...
661
662
  		struct ad_dpot_bus_data *bdata, unsigned long devid,
  			    const char *name)
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
663
  {
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
664

6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
665
666
  	struct dpot_data *data;
  	int i, err = 0;
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
667
668
669
670
671
672
  
  	data = kzalloc(sizeof(struct dpot_data), GFP_KERNEL);
  	if (!data) {
  		err = -ENOMEM;
  		goto exit;
  	}
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
673
  	dev_set_drvdata(dev, data);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
674
  	mutex_init(&data->update_lock);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
675
  	data->bdata = *bdata;
7f3379de9   Michael Hennerich   misc: ad525x_dpot...
676
  	data->devid = devid;
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
677

7f3379de9   Michael Hennerich   misc: ad525x_dpot...
678
  	data->max_pos = 1 << DPOT_MAX_POS(devid);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
679
  	data->rdac_mask = data->max_pos - 1;
7f3379de9   Michael Hennerich   misc: ad525x_dpot...
680
681
682
  	data->feat = DPOT_FEAT(devid);
  	data->uid = DPOT_UID(devid);
  	data->wipers = DPOT_WIPERS(devid);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
683

59592d0cc   Michael Hennerich   ad525x_dpot: add ...
684
  	for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
685
686
687
688
689
690
691
692
693
694
695
  		if (data->wipers & (1 << i)) {
  			err = ad_dpot_add_files(dev, data->feat, i);
  			if (err)
  				goto exit_remove_files;
  			/* power-up midscale */
  			if (data->feat & F_RDACS_WONLY)
  				data->rdac_cache[i] = data->max_pos / 2;
  		}
  
  	if (data->feat & F_CMD_INC)
  		err = sysfs_create_group(&dev->kobj, &ad525x_group_commands);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
696
697
698
699
700
701
  
  	if (err) {
  		dev_err(dev, "failed to register sysfs hooks
  ");
  		goto exit_free;
  	}
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
702
703
  	dev_info(dev, "%s %d-Position Digital Potentiometer registered
  ",
7f3379de9   Michael Hennerich   misc: ad525x_dpot...
704
  		 name, data->max_pos);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
705
706
  
  	return 0;
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
707
  exit_remove_files:
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
708
  	for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
709
710
  		if (data->wipers & (1 << i))
  			ad_dpot_remove_files(dev, data->feat, i);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
711
712
  exit_free:
  	kfree(data);
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
713
  	dev_set_drvdata(dev, NULL);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
714
  exit:
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
715
716
  	dev_err(dev, "failed to create client for %s ID 0x%lX
  ",
7f3379de9   Michael Hennerich   misc: ad525x_dpot...
717
  		name, devid);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
718
719
  	return err;
  }
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
720
  EXPORT_SYMBOL(ad_dpot_probe);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
721

0ed0d579c   Arnd Bergmann   misc: do not mark...
722
  int ad_dpot_remove(struct device *dev)
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
723
  {
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
724
725
  	struct dpot_data *data = dev_get_drvdata(dev);
  	int i;
59592d0cc   Michael Hennerich   ad525x_dpot: add ...
726
  	for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
727
728
  		if (data->wipers & (1 << i))
  			ad_dpot_remove_files(dev, data->feat, i);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
729

4eb174bee   Michael Hennerich   ad525x_dpot: new ...
730
731
732
733
  	kfree(data);
  
  	return 0;
  }
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
734
  EXPORT_SYMBOL(ad_dpot_remove);
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
735

4eb174bee   Michael Hennerich   ad525x_dpot: new ...
736
737
  
  MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>, "
6c536e4ce   Michael Hennerich   ad525x_dpot: add ...
738
739
  	      "Michael Hennerich <hennerich@blackfin.uclinux.org>");
  MODULE_DESCRIPTION("Digital potentiometer driver");
4eb174bee   Michael Hennerich   ad525x_dpot: new ...
740
  MODULE_LICENSE("GPL");