aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig32
-rw-r--r--drivers/misc/Makefile2
-rw-r--r--drivers/misc/ad525x_dpot-i2c.c134
-rw-r--r--drivers/misc/ad525x_dpot-spi.c172
-rw-r--r--drivers/misc/ad525x_dpot.c1016
-rw-r--r--drivers/misc/ad525x_dpot.h202
6 files changed, 1057 insertions, 501 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 0d0d625fece2..26386a92f5aa 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -14,11 +14,17 @@ menuconfig MISC_DEVICES
14if MISC_DEVICES 14if MISC_DEVICES
15 15
16config AD525X_DPOT 16config AD525X_DPOT
17 tristate "Analog Devices AD525x Digital Potentiometers" 17 tristate "Analog Devices Digital Potentiometers"
18 depends on I2C && SYSFS 18 depends on (I2C || SPI) && SYSFS
19 help 19 help
20 If you say yes here, you get support for the Analog Devices 20 If you say yes here, you get support for the Analog Devices
21 AD5258, AD5259, AD5251, AD5252, AD5253, AD5254 and AD5255 21 AD5258, AD5259, AD5251, AD5252, AD5253, AD5254, AD5255
22 AD5160, AD5161, AD5162, AD5165, AD5200, AD5201, AD5203,
23 AD5204, AD5206, AD5207, AD5231, AD5232, AD5233, AD5235,
24 AD5260, AD5262, AD5263, AD5290, AD5291, AD5292, AD5293,
25 AD7376, AD8400, AD8402, AD8403, ADN2850, AD5241, AD5242,
26 AD5243, AD5245, AD5246, AD5247, AD5248, AD5280, AD5282,
27 ADN2860, AD5273, AD5171, AD5170, AD5172, AD5173
22 digital potentiometer chips. 28 digital potentiometer chips.
23 29
24 See Documentation/misc-devices/ad525x_dpot.txt for the 30 See Documentation/misc-devices/ad525x_dpot.txt for the
@@ -27,6 +33,26 @@ config AD525X_DPOT
27 This driver can also be built as a module. If so, the module 33 This driver can also be built as a module. If so, the module
28 will be called ad525x_dpot. 34 will be called ad525x_dpot.
29 35
36config AD525X_DPOT_I2C
37 tristate "support I2C bus connection"
38 depends on AD525X_DPOT && I2C
39 help
40 Say Y here if you have a digital potentiometers hooked to an I2C bus.
41
42 To compile this driver as a module, choose M here: the
43 module will be called ad525x_dpot-i2c.
44
45config AD525X_DPOT_SPI
46 tristate "support SPI bus connection"
47 depends on AD525X_DPOT && SPI_MASTER
48 help
49 Say Y here if you have a digital potentiometers hooked to an SPI bus.
50
51 If unsure, say N (but it's safe to say "Y").
52
53 To compile this driver as a module, choose M here: the
54 module will be called ad525x_dpot-spi.
55
30config ATMEL_PWM 56config ATMEL_PWM
31 tristate "Atmel AT32/AT91 PWM support" 57 tristate "Atmel AT32/AT91 PWM support"
32 depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 58 depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f12dc3e54402..6ed06a19474a 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -4,6 +4,8 @@
4 4
5obj-$(CONFIG_IBM_ASM) += ibmasm/ 5obj-$(CONFIG_IBM_ASM) += ibmasm/
6obj-$(CONFIG_AD525X_DPOT) += ad525x_dpot.o 6obj-$(CONFIG_AD525X_DPOT) += ad525x_dpot.o
7obj-$(CONFIG_AD525X_DPOT_I2C) += ad525x_dpot-i2c.o
8obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o
7obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o 9obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
8obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o 10obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
9obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o 11obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c
new file mode 100644
index 000000000000..374352af7979
--- /dev/null
+++ b/drivers/misc/ad525x_dpot-i2c.c
@@ -0,0 +1,134 @@
1/*
2 * Driver for the Analog Devices digital potentiometers (I2C bus)
3 *
4 * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/i2c.h>
10#include <linux/module.h>
11
12#include "ad525x_dpot.h"
13
14/* ------------------------------------------------------------------------- */
15/* I2C bus functions */
16static int write_d8(void *client, u8 val)
17{
18 return i2c_smbus_write_byte(client, val);
19}
20
21static int write_r8d8(void *client, u8 reg, u8 val)
22{
23 return i2c_smbus_write_byte_data(client, reg, val);
24}
25
26static int write_r8d16(void *client, u8 reg, u16 val)
27{
28 return i2c_smbus_write_word_data(client, reg, val);
29}
30
31static int read_d8(void *client)
32{
33 return i2c_smbus_read_byte(client);
34}
35
36static int read_r8d8(void *client, u8 reg)
37{
38 return i2c_smbus_read_byte_data(client, reg);
39}
40
41static int read_r8d16(void *client, u8 reg)
42{
43 return i2c_smbus_read_word_data(client, reg);
44}
45
46static const struct ad_dpot_bus_ops bops = {
47 .read_d8 = read_d8,
48 .read_r8d8 = read_r8d8,
49 .read_r8d16 = read_r8d16,
50 .write_d8 = write_d8,
51 .write_r8d8 = write_r8d8,
52 .write_r8d16 = write_r8d16,
53};
54
55static int __devinit ad_dpot_i2c_probe(struct i2c_client *client,
56 const struct i2c_device_id *id)
57{
58 struct ad_dpot_bus_data bdata = {
59 .client = client,
60 .bops = &bops,
61 };
62
63 struct ad_dpot_id dpot_id = {
64 .name = (char *) &id->name,
65 .devid = id->driver_data,
66 };
67
68 if (!i2c_check_functionality(client->adapter,
69 I2C_FUNC_SMBUS_WORD_DATA)) {
70 dev_err(&client->dev, "SMBUS Word Data not Supported\n");
71 return -EIO;
72 }
73
74 return ad_dpot_probe(&client->dev, &bdata, &dpot_id);
75}
76
77static int __devexit ad_dpot_i2c_remove(struct i2c_client *client)
78{
79 return ad_dpot_remove(&client->dev);
80}
81
82static const struct i2c_device_id ad_dpot_id[] = {
83 {"ad5258", AD5258_ID},
84 {"ad5259", AD5259_ID},
85 {"ad5251", AD5251_ID},
86 {"ad5252", AD5252_ID},
87 {"ad5253", AD5253_ID},
88 {"ad5254", AD5254_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},
97 {"ad5280", AD5280_ID},
98 {"ad5282", AD5282_ID},
99 {"adn2860", ADN2860_ID},
100 {"ad5273", AD5273_ID},
101 {"ad5171", AD5171_ID},
102 {"ad5170", AD5170_ID},
103 {"ad5172", AD5172_ID},
104 {"ad5173", AD5173_ID},
105 {}
106};
107MODULE_DEVICE_TABLE(i2c, ad_dpot_id);
108
109static struct i2c_driver ad_dpot_i2c_driver = {
110 .driver = {
111 .name = "ad_dpot",
112 .owner = THIS_MODULE,
113 },
114 .probe = ad_dpot_i2c_probe,
115 .remove = __devexit_p(ad_dpot_i2c_remove),
116 .id_table = ad_dpot_id,
117};
118
119static int __init ad_dpot_i2c_init(void)
120{
121 return i2c_add_driver(&ad_dpot_i2c_driver);
122}
123module_init(ad_dpot_i2c_init);
124
125static void __exit ad_dpot_i2c_exit(void)
126{
127 i2c_del_driver(&ad_dpot_i2c_driver);
128}
129module_exit(ad_dpot_i2c_exit);
130
131MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
132MODULE_DESCRIPTION("digital potentiometer I2C bus driver");
133MODULE_LICENSE("GPL");
134MODULE_ALIAS("i2c:ad_dpot");
diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c
new file mode 100644
index 000000000000..b8c6df9c8437
--- /dev/null
+++ b/drivers/misc/ad525x_dpot-spi.c
@@ -0,0 +1,172 @@
1/*
2 * Driver for the Analog Devices digital potentiometers (SPI bus)
3 *
4 * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/spi/spi.h>
10#include <linux/module.h>
11
12#include "ad525x_dpot.h"
13
14static const struct ad_dpot_id ad_dpot_spi_devlist[] = {
15 {.name = "ad5160", .devid = AD5160_ID},
16 {.name = "ad5161", .devid = AD5161_ID},
17 {.name = "ad5162", .devid = AD5162_ID},
18 {.name = "ad5165", .devid = AD5165_ID},
19 {.name = "ad5200", .devid = AD5200_ID},
20 {.name = "ad5201", .devid = AD5201_ID},
21 {.name = "ad5203", .devid = AD5203_ID},
22 {.name = "ad5204", .devid = AD5204_ID},
23 {.name = "ad5206", .devid = AD5206_ID},
24 {.name = "ad5207", .devid = AD5207_ID},
25 {.name = "ad5231", .devid = AD5231_ID},
26 {.name = "ad5232", .devid = AD5232_ID},
27 {.name = "ad5233", .devid = AD5233_ID},
28 {.name = "ad5235", .devid = AD5235_ID},
29 {.name = "ad5260", .devid = AD5260_ID},
30 {.name = "ad5262", .devid = AD5262_ID},
31 {.name = "ad5263", .devid = AD5263_ID},
32 {.name = "ad5290", .devid = AD5290_ID},
33 {.name = "ad5291", .devid = AD5291_ID},
34 {.name = "ad5292", .devid = AD5292_ID},
35 {.name = "ad5293", .devid = AD5293_ID},
36 {.name = "ad7376", .devid = AD7376_ID},
37 {.name = "ad8400", .devid = AD8400_ID},
38 {.name = "ad8402", .devid = AD8402_ID},
39 {.name = "ad8403", .devid = AD8403_ID},
40 {.name = "adn2850", .devid = ADN2850_ID},
41 {}
42};
43
44/* ------------------------------------------------------------------------- */
45
46/* SPI bus functions */
47static int write8(void *client, u8 val)
48{
49 u8 data = val;
50 return spi_write(client, &data, 1);
51}
52
53static int write16(void *client, u8 reg, u8 val)
54{
55 u8 data[2] = {reg, val};
56 return spi_write(client, data, 1);
57}
58
59static int write24(void *client, u8 reg, u16 val)
60{
61 u8 data[3] = {reg, val >> 8, val};
62 return spi_write(client, data, 1);
63}
64
65static int read8(void *client)
66{
67 int ret;
68 u8 data;
69 ret = spi_read(client, &data, 1);
70 if (ret < 0)
71 return ret;
72
73 return data;
74}
75
76static int read16(void *client, u8 reg)
77{
78 int ret;
79 u8 buf_rx[2];
80
81 write16(client, reg, 0);
82 ret = spi_read(client, buf_rx, 2);
83 if (ret < 0)
84 return ret;
85
86 return (buf_rx[0] << 8) | buf_rx[1];
87}
88
89static int read24(void *client, u8 reg)
90{
91 int ret;
92 u8 buf_rx[3];
93
94 write24(client, reg, 0);
95 ret = spi_read(client, buf_rx, 3);
96 if (ret < 0)
97 return ret;
98
99 return (buf_rx[1] << 8) | buf_rx[2];
100}
101
102static const struct ad_dpot_bus_ops bops = {
103 .read_d8 = read8,
104 .read_r8d8 = read16,
105 .read_r8d16 = read24,
106 .write_d8 = write8,
107 .write_r8d8 = write16,
108 .write_r8d16 = write24,
109};
110
111static const struct ad_dpot_id *dpot_match_id(const struct ad_dpot_id *id,
112 char *name)
113{
114 while (id->name && id->name[0]) {
115 if (strcmp(name, id->name) == 0)
116 return id;
117 id++;
118 }
119 return NULL;
120}
121
122static int __devinit ad_dpot_spi_probe(struct spi_device *spi)
123{
124 char *name = spi->dev.platform_data;
125 const struct ad_dpot_id *dpot_id;
126
127 struct ad_dpot_bus_data bdata = {
128 .client = spi,
129 .bops = &bops,
130 };
131
132 dpot_id = dpot_match_id(ad_dpot_spi_devlist, name);
133
134 if (dpot_id == NULL) {
135 dev_err(&spi->dev, "%s not in supported device list", name);
136 return -ENODEV;
137 }
138
139 return ad_dpot_probe(&spi->dev, &bdata, dpot_id);
140}
141
142static int __devexit ad_dpot_spi_remove(struct spi_device *spi)
143{
144 return ad_dpot_remove(&spi->dev);
145}
146
147static struct spi_driver ad_dpot_spi_driver = {
148 .driver = {
149 .name = "ad_dpot",
150 .bus = &spi_bus_type,
151 .owner = THIS_MODULE,
152 },
153 .probe = ad_dpot_spi_probe,
154 .remove = __devexit_p(ad_dpot_spi_remove),
155};
156
157static int __init ad_dpot_spi_init(void)
158{
159 return spi_register_driver(&ad_dpot_spi_driver);
160}
161module_init(ad_dpot_spi_init);
162
163static void __exit ad_dpot_spi_exit(void)
164{
165 spi_unregister_driver(&ad_dpot_spi_driver);
166}
167module_exit(ad_dpot_spi_exit);
168
169MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
170MODULE_DESCRIPTION("digital potentiometer SPI bus driver");
171MODULE_LICENSE("GPL");
172MODULE_ALIAS("spi:ad_dpot");
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c
index 30a59f2bacd2..5e6fa8449e8b 100644
--- a/drivers/misc/ad525x_dpot.c
+++ b/drivers/misc/ad525x_dpot.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * ad525x_dpot: Driver for the Analog Devices AD525x digital potentiometers 2 * ad525x_dpot: Driver for the Analog Devices digital potentiometers
3 * Copyright (c) 2009 Analog Devices, Inc. 3 * Copyright (c) 2009-2010 Analog Devices, Inc.
4 * Author: Michael Hennerich <hennerich@blackfin.uclinux.org> 4 * Author: Michael Hennerich <hennerich@blackfin.uclinux.org>
5 * 5 *
6 * DEVID #Wipers #Positions Resistor Options (kOhm) 6 * DEVID #Wipers #Positions Resistor Options (kOhm)
@@ -11,6 +11,47 @@
11 * AD5255 3 512 25, 250 11 * AD5255 3 512 25, 250
12 * AD5253 4 64 1, 10, 50, 100 12 * AD5253 4 64 1, 10, 50, 100
13 * AD5254 4 256 1, 10, 50, 100 13 * AD5254 4 256 1, 10, 50, 100
14 * AD5160 1 256 5, 10, 50, 100
15 * AD5161 1 256 5, 10, 50, 100
16 * AD5162 2 256 2.5, 10, 50, 100
17 * AD5165 1 256 100
18 * AD5200 1 256 10, 50
19 * AD5201 1 33 10, 50
20 * AD5203 4 64 10, 100
21 * AD5204 4 256 10, 50, 100
22 * AD5206 6 256 10, 50, 100
23 * AD5207 2 256 10, 50, 100
24 * AD5231 1 1024 10, 50, 100
25 * AD5232 2 256 10, 50, 100
26 * AD5233 4 64 10, 50, 100
27 * AD5235 2 1024 25, 250
28 * AD5260 1 256 20, 50, 200
29 * AD5262 2 256 20, 50, 200
30 * AD5263 4 256 20, 50, 200
31 * AD5290 1 256 10, 50, 100
32 * AD5291 1 256 20
33 * AD5292 1 1024 20
34 * AD5293 1 1024 20
35 * AD7376 1 128 10, 50, 100, 1M
36 * AD8400 1 256 1, 10, 50, 100
37 * AD8402 2 256 1, 10, 50, 100
38 * AD8403 4 256 1, 10, 50, 100
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
47 * AD5280 1 256 20, 50, 200
48 * AD5282 2 256 20, 50, 200
49 * ADN2860 3 512 25, 250
50 * AD5273 1 64 1, 10, 50, 100 (OTP)
51 * AD5171 1 64 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)
54 * AD5173 2 256 2.5, 10, 50, 100 (OTP)
14 * 55 *
15 * See Documentation/misc-devices/ad525x_dpot.txt for more info. 56 * See Documentation/misc-devices/ad525x_dpot.txt for more info.
16 * 57 *
@@ -28,77 +69,283 @@
28#include <linux/device.h> 69#include <linux/device.h>
29#include <linux/kernel.h> 70#include <linux/kernel.h>
30#include <linux/init.h> 71#include <linux/init.h>
31#include <linux/slab.h>
32#include <linux/i2c.h>
33#include <linux/delay.h> 72#include <linux/delay.h>
73#include <linux/slab.h>
34 74
35#define DRIVER_NAME "ad525x_dpot" 75#define DRIVER_VERSION "0.2"
36#define DRIVER_VERSION "0.1"
37
38enum dpot_devid {
39 AD5258_ID,
40 AD5259_ID,
41 AD5251_ID,
42 AD5252_ID,
43 AD5253_ID,
44 AD5254_ID,
45 AD5255_ID,
46};
47 76
48#define AD5258_MAX_POSITION 64 77#include "ad525x_dpot.h"
49#define AD5259_MAX_POSITION 256
50#define AD5251_MAX_POSITION 64
51#define AD5252_MAX_POSITION 256
52#define AD5253_MAX_POSITION 64
53#define AD5254_MAX_POSITION 256
54#define AD5255_MAX_POSITION 512
55
56#define AD525X_RDAC0 0
57#define AD525X_RDAC1 1
58#define AD525X_RDAC2 2
59#define AD525X_RDAC3 3
60
61#define AD525X_REG_TOL 0x18
62#define AD525X_TOL_RDAC0 (AD525X_REG_TOL | AD525X_RDAC0)
63#define AD525X_TOL_RDAC1 (AD525X_REG_TOL | AD525X_RDAC1)
64#define AD525X_TOL_RDAC2 (AD525X_REG_TOL | AD525X_RDAC2)
65#define AD525X_TOL_RDAC3 (AD525X_REG_TOL | AD525X_RDAC3)
66
67/* RDAC-to-EEPROM Interface Commands */
68#define AD525X_I2C_RDAC (0x00 << 5)
69#define AD525X_I2C_EEPROM (0x01 << 5)
70#define AD525X_I2C_CMD (0x80)
71
72#define AD525X_DEC_ALL_6DB (AD525X_I2C_CMD | (0x4 << 3))
73#define AD525X_INC_ALL_6DB (AD525X_I2C_CMD | (0x9 << 3))
74#define AD525X_DEC_ALL (AD525X_I2C_CMD | (0x6 << 3))
75#define AD525X_INC_ALL (AD525X_I2C_CMD | (0xB << 3))
76
77static s32 ad525x_read(struct i2c_client *client, u8 reg);
78static s32 ad525x_write(struct i2c_client *client, u8 reg, u8 value);
79 78
80/* 79/*
81 * Client data (each client gets its own) 80 * Client data (each client gets its own)
82 */ 81 */
83 82
84struct dpot_data { 83struct dpot_data {
84 struct ad_dpot_bus_data bdata;
85 struct mutex update_lock; 85 struct mutex update_lock;
86 unsigned rdac_mask; 86 unsigned rdac_mask;
87 unsigned max_pos; 87 unsigned max_pos;
88 unsigned devid; 88 unsigned long devid;
89 unsigned uid;
90 unsigned feat;
91 unsigned wipers;
92 u16 rdac_cache[MAX_RDACS];
93 DECLARE_BITMAP(otp_en_mask, MAX_RDACS);
89}; 94};
90 95
96static inline int dpot_read_d8(struct dpot_data *dpot)
97{
98 return dpot->bdata.bops->read_d8(dpot->bdata.client);
99}
100
101static inline int dpot_read_r8d8(struct dpot_data *dpot, u8 reg)
102{
103 return dpot->bdata.bops->read_r8d8(dpot->bdata.client, reg);
104}
105
106static inline int dpot_read_r8d16(struct dpot_data *dpot, u8 reg)
107{
108 return dpot->bdata.bops->read_r8d16(dpot->bdata.client, reg);
109}
110
111static inline int dpot_write_d8(struct dpot_data *dpot, u8 val)
112{
113 return dpot->bdata.bops->write_d8(dpot->bdata.client, val);
114}
115
116static inline int dpot_write_r8d8(struct dpot_data *dpot, u8 reg, u16 val)
117{
118 return dpot->bdata.bops->write_r8d8(dpot->bdata.client, reg, val);
119}
120
121static inline int dpot_write_r8d16(struct dpot_data *dpot, u8 reg, u16 val)
122{
123 return dpot->bdata.bops->write_r8d16(dpot->bdata.client, reg, val);
124}
125
126static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg)
127{
128 unsigned ctrl = 0;
129
130 if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
131
132 if (dpot->feat & F_RDACS_WONLY)
133 return dpot->rdac_cache[reg & DPOT_RDAC_MASK];
134
135 if (dpot->uid == DPOT_UID(AD5291_ID) ||
136 dpot->uid == DPOT_UID(AD5292_ID) ||
137 dpot->uid == DPOT_UID(AD5293_ID))
138 return dpot_read_r8d8(dpot,
139 DPOT_AD5291_READ_RDAC << 2);
140
141 ctrl = DPOT_SPI_READ_RDAC;
142 } else if (reg & DPOT_ADDR_EEPROM) {
143 ctrl = DPOT_SPI_READ_EEPROM;
144 }
145
146 if (dpot->feat & F_SPI_16BIT)
147 return dpot_read_r8d8(dpot, ctrl);
148 else if (dpot->feat & F_SPI_24BIT)
149 return dpot_read_r8d16(dpot, ctrl);
150
151 return -EFAULT;
152}
153
154static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
155{
156 unsigned ctrl = 0;
157 switch (dpot->uid) {
158 case DPOT_UID(AD5246_ID):
159 case DPOT_UID(AD5247_ID):
160 return dpot_read_d8(dpot);
161 case DPOT_UID(AD5245_ID):
162 case DPOT_UID(AD5241_ID):
163 case DPOT_UID(AD5242_ID):
164 case DPOT_UID(AD5243_ID):
165 case DPOT_UID(AD5248_ID):
166 case DPOT_UID(AD5280_ID):
167 case DPOT_UID(AD5282_ID):
168 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
169 0 : DPOT_AD5291_RDAC_AB;
170 return dpot_read_r8d8(dpot, ctrl);
171 case DPOT_UID(AD5170_ID):
172 case DPOT_UID(AD5171_ID):
173 case DPOT_UID(AD5273_ID):
174 return dpot_read_d8(dpot);
175 case DPOT_UID(AD5172_ID):
176 case DPOT_UID(AD5173_ID):
177 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
178 0 : DPOT_AD5272_3_A0;
179 return dpot_read_r8d8(dpot, ctrl);
180 default:
181 if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256))
182 return dpot_read_r8d16(dpot, (reg & 0xF8) |
183 ((reg & 0x7) << 1));
184 else
185 return dpot_read_r8d8(dpot, reg);
186 }
187}
188
189static s32 dpot_read(struct dpot_data *dpot, u8 reg)
190{
191 if (dpot->feat & F_SPI)
192 return dpot_read_spi(dpot, reg);
193 else
194 return dpot_read_i2c(dpot, reg);
195}
196
197static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
198{
199 unsigned val = 0;
200
201 if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
202 if (dpot->feat & F_RDACS_WONLY)
203 dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value;
204
205 if (dpot->feat & F_AD_APPDATA) {
206 if (dpot->feat & F_SPI_8BIT) {
207 val = ((reg & DPOT_RDAC_MASK) <<
208 DPOT_MAX_POS(dpot->devid)) |
209 value;
210 return dpot_write_d8(dpot, val);
211 } else if (dpot->feat & F_SPI_16BIT) {
212 val = ((reg & DPOT_RDAC_MASK) <<
213 DPOT_MAX_POS(dpot->devid)) |
214 value;
215 return dpot_write_r8d8(dpot, val >> 8,
216 val & 0xFF);
217 } else
218 BUG();
219 } else {
220 if (dpot->uid == DPOT_UID(AD5291_ID) ||
221 dpot->uid == DPOT_UID(AD5292_ID) ||
222 dpot->uid == DPOT_UID(AD5293_ID))
223 return dpot_write_r8d8(dpot,
224 (DPOT_AD5291_RDAC << 2) |
225 (value >> 8), value & 0xFF);
226
227 val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK);
228 }
229 } else if (reg & DPOT_ADDR_EEPROM) {
230 val = DPOT_SPI_EEPROM | (reg & DPOT_RDAC_MASK);
231 } else if (reg & DPOT_ADDR_CMD) {
232 switch (reg) {
233 case DPOT_DEC_ALL_6DB:
234 val = DPOT_SPI_DEC_ALL_6DB;
235 break;
236 case DPOT_INC_ALL_6DB:
237 val = DPOT_SPI_INC_ALL_6DB;
238 break;
239 case DPOT_DEC_ALL:
240 val = DPOT_SPI_DEC_ALL;
241 break;
242 case DPOT_INC_ALL:
243 val = DPOT_SPI_INC_ALL;
244 break;
245 }
246 } else
247 BUG();
248
249 if (dpot->feat & F_SPI_16BIT)
250 return dpot_write_r8d8(dpot, val, value);
251 else if (dpot->feat & F_SPI_24BIT)
252 return dpot_write_r8d16(dpot, val, value);
253
254 return -EFAULT;
255}
256
257static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
258{
259 /* Only write the instruction byte for certain commands */
260 unsigned tmp = 0, ctrl = 0;
261
262 switch (dpot->uid) {
263 case DPOT_UID(AD5246_ID):
264 case DPOT_UID(AD5247_ID):
265 return dpot_write_d8(dpot, value);
266 break;
267
268 case DPOT_UID(AD5245_ID):
269 case DPOT_UID(AD5241_ID):
270 case DPOT_UID(AD5242_ID):
271 case DPOT_UID(AD5243_ID):
272 case DPOT_UID(AD5248_ID):
273 case DPOT_UID(AD5280_ID):
274 case DPOT_UID(AD5282_ID):
275 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
276 0 : DPOT_AD5291_RDAC_AB;
277 return dpot_write_r8d8(dpot, ctrl, value);
278 break;
279 case DPOT_UID(AD5171_ID):
280 case DPOT_UID(AD5273_ID):
281 if (reg & DPOT_ADDR_OTP) {
282 tmp = dpot_read_d8(dpot);
283 if (tmp >> 6) /* Ready to Program? */
284 return -EFAULT;
285 ctrl = DPOT_AD5273_FUSE;
286 }
287 return dpot_write_r8d8(dpot, ctrl, value);
288 break;
289 case DPOT_UID(AD5172_ID):
290 case DPOT_UID(AD5173_ID):
291 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
292 0 : DPOT_AD5272_3_A0;
293 if (reg & DPOT_ADDR_OTP) {
294 tmp = dpot_read_r8d16(dpot, ctrl);
295 if (tmp >> 14) /* Ready to Program? */
296 return -EFAULT;
297 ctrl |= DPOT_AD5270_2_3_FUSE;
298 }
299 return dpot_write_r8d8(dpot, ctrl, value);
300 break;
301 case DPOT_UID(AD5170_ID):
302 if (reg & DPOT_ADDR_OTP) {
303 tmp = dpot_read_r8d16(dpot, tmp);
304 if (tmp >> 14) /* Ready to Program? */
305 return -EFAULT;
306 ctrl = DPOT_AD5270_2_3_FUSE;
307 }
308 return dpot_write_r8d8(dpot, ctrl, value);
309 break;
310 default:
311 if (reg & DPOT_ADDR_CMD)
312 return dpot_write_d8(dpot, reg);
313
314 if (dpot->max_pos > 256)
315 return dpot_write_r8d16(dpot, (reg & 0xF8) |
316 ((reg & 0x7) << 1), value);
317 else
318 /* All other registers require instruction + data bytes */
319 return dpot_write_r8d8(dpot, reg, value);
320 }
321}
322
323
324static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value)
325{
326 if (dpot->feat & F_SPI)
327 return dpot_write_spi(dpot, reg, value);
328 else
329 return dpot_write_i2c(dpot, reg, value);
330}
331
91/* sysfs functions */ 332/* sysfs functions */
92 333
93static ssize_t sysfs_show_reg(struct device *dev, 334static ssize_t sysfs_show_reg(struct device *dev,
94 struct device_attribute *attr, char *buf, u32 reg) 335 struct device_attribute *attr,
336 char *buf, u32 reg)
95{ 337{
96 struct i2c_client *client = to_i2c_client(dev); 338 struct dpot_data *data = dev_get_drvdata(dev);
97 struct dpot_data *data = i2c_get_clientdata(client);
98 s32 value; 339 s32 value;
99 340
341 if (reg & DPOT_ADDR_OTP_EN)
342 return sprintf(buf, "%s\n",
343 test_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask) ?
344 "enabled" : "disabled");
345
346
100 mutex_lock(&data->update_lock); 347 mutex_lock(&data->update_lock);
101 value = ad525x_read(client, reg); 348 value = dpot_read(data, reg);
102 mutex_unlock(&data->update_lock); 349 mutex_unlock(&data->update_lock);
103 350
104 if (value < 0) 351 if (value < 0)
@@ -111,7 +358,7 @@ static ssize_t sysfs_show_reg(struct device *dev,
111 * datasheet (Rev. A) for more details. 358 * datasheet (Rev. A) for more details.
112 */ 359 */
113 360
114 if (reg & AD525X_REG_TOL) 361 if (reg & DPOT_REG_TOL)
115 return sprintf(buf, "0x%04x\n", value & 0xFFFF); 362 return sprintf(buf, "0x%04x\n", value & 0xFFFF);
116 else 363 else
117 return sprintf(buf, "%u\n", value & data->rdac_mask); 364 return sprintf(buf, "%u\n", value & data->rdac_mask);
@@ -121,11 +368,23 @@ static ssize_t sysfs_set_reg(struct device *dev,
121 struct device_attribute *attr, 368 struct device_attribute *attr,
122 const char *buf, size_t count, u32 reg) 369 const char *buf, size_t count, u32 reg)
123{ 370{
124 struct i2c_client *client = to_i2c_client(dev); 371 struct dpot_data *data = dev_get_drvdata(dev);
125 struct dpot_data *data = i2c_get_clientdata(client);
126 unsigned long value; 372 unsigned long value;
127 int err; 373 int err;
128 374
375 if (reg & DPOT_ADDR_OTP_EN) {
376 if (!strncmp(buf, "enabled", sizeof("enabled")))
377 set_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask);
378 else
379 clear_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask);
380
381 return count;
382 }
383
384 if ((reg & DPOT_ADDR_OTP) &&
385 !test_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask))
386 return -EPERM;
387
129 err = strict_strtoul(buf, 10, &value); 388 err = strict_strtoul(buf, 10, &value);
130 if (err) 389 if (err)
131 return err; 390 return err;
@@ -134,9 +393,11 @@ static ssize_t sysfs_set_reg(struct device *dev,
134 value = data->rdac_mask; 393 value = data->rdac_mask;
135 394
136 mutex_lock(&data->update_lock); 395 mutex_lock(&data->update_lock);
137 ad525x_write(client, reg, value); 396 dpot_write(data, reg, value);
138 if (reg & AD525X_I2C_EEPROM) 397 if (reg & DPOT_ADDR_EEPROM)
139 msleep(26); /* Sleep while the EEPROM updates */ 398 msleep(26); /* Sleep while the EEPROM updates */
399 else if (reg & DPOT_ADDR_OTP)
400 msleep(400); /* Sleep while the OTP updates */
140 mutex_unlock(&data->update_lock); 401 mutex_unlock(&data->update_lock);
141 402
142 return count; 403 return count;
@@ -146,11 +407,10 @@ static ssize_t sysfs_do_cmd(struct device *dev,
146 struct device_attribute *attr, 407 struct device_attribute *attr,
147 const char *buf, size_t count, u32 reg) 408 const char *buf, size_t count, u32 reg)
148{ 409{
149 struct i2c_client *client = to_i2c_client(dev); 410 struct dpot_data *data = dev_get_drvdata(dev);
150 struct dpot_data *data = i2c_get_clientdata(client);
151 411
152 mutex_lock(&data->update_lock); 412 mutex_lock(&data->update_lock);
153 ad525x_write(client, reg, 0); 413 dpot_write(data, reg, 0);
154 mutex_unlock(&data->update_lock); 414 mutex_unlock(&data->update_lock);
155 415
156 return count; 416 return count;
@@ -158,244 +418,131 @@ static ssize_t sysfs_do_cmd(struct device *dev,
158 418
159/* ------------------------------------------------------------------------- */ 419/* ------------------------------------------------------------------------- */
160 420
161static ssize_t show_rdac0(struct device *dev, 421#define DPOT_DEVICE_SHOW(_name, _reg) static ssize_t \
162 struct device_attribute *attr, char *buf) 422show_##_name(struct device *dev, \
163{ 423 struct device_attribute *attr, char *buf) \
164 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC0); 424{ \
165} 425 return sysfs_show_reg(dev, attr, buf, _reg); \
166 426}
167static ssize_t set_rdac0(struct device *dev, 427
168 struct device_attribute *attr, 428#define DPOT_DEVICE_SET(_name, _reg) static ssize_t \
169 const char *buf, size_t count) 429set_##_name(struct device *dev, \
170{ 430 struct device_attribute *attr, \
171 return sysfs_set_reg(dev, attr, buf, count, 431 const char *buf, size_t count) \
172 AD525X_I2C_RDAC | AD525X_RDAC0); 432{ \
173} 433 return sysfs_set_reg(dev, attr, buf, count, _reg); \
174 434}
175static DEVICE_ATTR(rdac0, S_IWUSR | S_IRUGO, show_rdac0, set_rdac0); 435
176 436#define DPOT_DEVICE_SHOW_SET(name, reg) \
177static ssize_t show_eeprom0(struct device *dev, 437DPOT_DEVICE_SHOW(name, reg) \
178 struct device_attribute *attr, char *buf) 438DPOT_DEVICE_SET(name, reg) \
179{ 439static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, show_##name, set_##name);
180 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC0); 440
181} 441#define DPOT_DEVICE_SHOW_ONLY(name, reg) \
182 442DPOT_DEVICE_SHOW(name, reg) \
183static ssize_t set_eeprom0(struct device *dev, 443static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, show_##name, NULL);
184 struct device_attribute *attr, 444
185 const char *buf, size_t count) 445DPOT_DEVICE_SHOW_SET(rdac0, DPOT_ADDR_RDAC | DPOT_RDAC0);
186{ 446DPOT_DEVICE_SHOW_SET(eeprom0, DPOT_ADDR_EEPROM | DPOT_RDAC0);
187 return sysfs_set_reg(dev, attr, buf, count, 447DPOT_DEVICE_SHOW_ONLY(tolerance0, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC0);
188 AD525X_I2C_EEPROM | AD525X_RDAC0); 448DPOT_DEVICE_SHOW_SET(otp0, DPOT_ADDR_OTP | DPOT_RDAC0);
189} 449DPOT_DEVICE_SHOW_SET(otp0en, DPOT_ADDR_OTP_EN | DPOT_RDAC0);
190 450
191static DEVICE_ATTR(eeprom0, S_IWUSR | S_IRUGO, show_eeprom0, set_eeprom0); 451DPOT_DEVICE_SHOW_SET(rdac1, DPOT_ADDR_RDAC | DPOT_RDAC1);
192 452DPOT_DEVICE_SHOW_SET(eeprom1, DPOT_ADDR_EEPROM | DPOT_RDAC1);
193static ssize_t show_tolerance0(struct device *dev, 453DPOT_DEVICE_SHOW_ONLY(tolerance1, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC1);
194 struct device_attribute *attr, char *buf) 454DPOT_DEVICE_SHOW_SET(otp1, DPOT_ADDR_OTP | DPOT_RDAC1);
195{ 455DPOT_DEVICE_SHOW_SET(otp1en, DPOT_ADDR_OTP_EN | DPOT_RDAC1);
196 return sysfs_show_reg(dev, attr, buf, 456
197 AD525X_I2C_EEPROM | AD525X_TOL_RDAC0); 457DPOT_DEVICE_SHOW_SET(rdac2, DPOT_ADDR_RDAC | DPOT_RDAC2);
198} 458DPOT_DEVICE_SHOW_SET(eeprom2, DPOT_ADDR_EEPROM | DPOT_RDAC2);
199 459DPOT_DEVICE_SHOW_ONLY(tolerance2, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC2);
200static DEVICE_ATTR(tolerance0, S_IRUGO, show_tolerance0, NULL); 460DPOT_DEVICE_SHOW_SET(otp2, DPOT_ADDR_OTP | DPOT_RDAC2);
201 461DPOT_DEVICE_SHOW_SET(otp2en, DPOT_ADDR_OTP_EN | DPOT_RDAC2);
202/* ------------------------------------------------------------------------- */ 462
203 463DPOT_DEVICE_SHOW_SET(rdac3, DPOT_ADDR_RDAC | DPOT_RDAC3);
204static ssize_t show_rdac1(struct device *dev, 464DPOT_DEVICE_SHOW_SET(eeprom3, DPOT_ADDR_EEPROM | DPOT_RDAC3);
205 struct device_attribute *attr, char *buf) 465DPOT_DEVICE_SHOW_ONLY(tolerance3, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC3);
206{ 466DPOT_DEVICE_SHOW_SET(otp3, DPOT_ADDR_OTP | DPOT_RDAC3);
207 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC1); 467DPOT_DEVICE_SHOW_SET(otp3en, DPOT_ADDR_OTP_EN | DPOT_RDAC3);
208} 468
209 469DPOT_DEVICE_SHOW_SET(rdac4, DPOT_ADDR_RDAC | DPOT_RDAC4);
210static ssize_t set_rdac1(struct device *dev, 470DPOT_DEVICE_SHOW_SET(eeprom4, DPOT_ADDR_EEPROM | DPOT_RDAC4);
211 struct device_attribute *attr, 471DPOT_DEVICE_SHOW_ONLY(tolerance4, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC4);
212 const char *buf, size_t count) 472DPOT_DEVICE_SHOW_SET(otp4, DPOT_ADDR_OTP | DPOT_RDAC4);
213{ 473DPOT_DEVICE_SHOW_SET(otp4en, DPOT_ADDR_OTP_EN | DPOT_RDAC4);
214 return sysfs_set_reg(dev, attr, buf, count, 474
215 AD525X_I2C_RDAC | AD525X_RDAC1); 475DPOT_DEVICE_SHOW_SET(rdac5, DPOT_ADDR_RDAC | DPOT_RDAC5);
216} 476DPOT_DEVICE_SHOW_SET(eeprom5, DPOT_ADDR_EEPROM | DPOT_RDAC5);
217 477DPOT_DEVICE_SHOW_ONLY(tolerance5, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC5);
218static DEVICE_ATTR(rdac1, S_IWUSR | S_IRUGO, show_rdac1, set_rdac1); 478DPOT_DEVICE_SHOW_SET(otp5, DPOT_ADDR_OTP | DPOT_RDAC5);
219 479DPOT_DEVICE_SHOW_SET(otp5en, DPOT_ADDR_OTP_EN | DPOT_RDAC5);
220static ssize_t show_eeprom1(struct device *dev, 480
221 struct device_attribute *attr, char *buf) 481static const struct attribute *dpot_attrib_wipers[] = {
222{ 482 &dev_attr_rdac0.attr,
223 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC1); 483 &dev_attr_rdac1.attr,
224} 484 &dev_attr_rdac2.attr,
225 485 &dev_attr_rdac3.attr,
226static ssize_t set_eeprom1(struct device *dev, 486 &dev_attr_rdac4.attr,
227 struct device_attribute *attr, 487 &dev_attr_rdac5.attr,
228 const char *buf, size_t count) 488 NULL
229{ 489};
230 return sysfs_set_reg(dev, attr, buf, count,
231 AD525X_I2C_EEPROM | AD525X_RDAC1);
232}
233
234static DEVICE_ATTR(eeprom1, S_IWUSR | S_IRUGO, show_eeprom1, set_eeprom1);
235
236static ssize_t show_tolerance1(struct device *dev,
237 struct device_attribute *attr, char *buf)
238{
239 return sysfs_show_reg(dev, attr, buf,
240 AD525X_I2C_EEPROM | AD525X_TOL_RDAC1);
241}
242
243static DEVICE_ATTR(tolerance1, S_IRUGO, show_tolerance1, NULL);
244
245/* ------------------------------------------------------------------------- */
246
247static ssize_t show_rdac2(struct device *dev,
248 struct device_attribute *attr, char *buf)
249{
250 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC2);
251}
252
253static ssize_t set_rdac2(struct device *dev,
254 struct device_attribute *attr,
255 const char *buf, size_t count)
256{
257 return sysfs_set_reg(dev, attr, buf, count,
258 AD525X_I2C_RDAC | AD525X_RDAC2);
259}
260
261static DEVICE_ATTR(rdac2, S_IWUSR | S_IRUGO, show_rdac2, set_rdac2);
262
263static ssize_t show_eeprom2(struct device *dev,
264 struct device_attribute *attr, char *buf)
265{
266 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC2);
267}
268
269static ssize_t set_eeprom2(struct device *dev,
270 struct device_attribute *attr,
271 const char *buf, size_t count)
272{
273 return sysfs_set_reg(dev, attr, buf, count,
274 AD525X_I2C_EEPROM | AD525X_RDAC2);
275}
276
277static DEVICE_ATTR(eeprom2, S_IWUSR | S_IRUGO, show_eeprom2, set_eeprom2);
278
279static ssize_t show_tolerance2(struct device *dev,
280 struct device_attribute *attr, char *buf)
281{
282 return sysfs_show_reg(dev, attr, buf,
283 AD525X_I2C_EEPROM | AD525X_TOL_RDAC2);
284}
285
286static DEVICE_ATTR(tolerance2, S_IRUGO, show_tolerance2, NULL);
287
288/* ------------------------------------------------------------------------- */
289
290static ssize_t show_rdac3(struct device *dev,
291 struct device_attribute *attr, char *buf)
292{
293 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC3);
294}
295
296static ssize_t set_rdac3(struct device *dev,
297 struct device_attribute *attr,
298 const char *buf, size_t count)
299{
300 return sysfs_set_reg(dev, attr, buf, count,
301 AD525X_I2C_RDAC | AD525X_RDAC3);
302}
303
304static DEVICE_ATTR(rdac3, S_IWUSR | S_IRUGO, show_rdac3, set_rdac3);
305
306static ssize_t show_eeprom3(struct device *dev,
307 struct device_attribute *attr, char *buf)
308{
309 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC3);
310}
311
312static ssize_t set_eeprom3(struct device *dev,
313 struct device_attribute *attr,
314 const char *buf, size_t count)
315{
316 return sysfs_set_reg(dev, attr, buf, count,
317 AD525X_I2C_EEPROM | AD525X_RDAC3);
318}
319 490
320static DEVICE_ATTR(eeprom3, S_IWUSR | S_IRUGO, show_eeprom3, set_eeprom3); 491static const struct attribute *dpot_attrib_eeprom[] = {
492 &dev_attr_eeprom0.attr,
493 &dev_attr_eeprom1.attr,
494 &dev_attr_eeprom2.attr,
495 &dev_attr_eeprom3.attr,
496 &dev_attr_eeprom4.attr,
497 &dev_attr_eeprom5.attr,
498 NULL
499};
321 500
322static ssize_t show_tolerance3(struct device *dev, 501static const struct attribute *dpot_attrib_otp[] = {
323 struct device_attribute *attr, char *buf) 502 &dev_attr_otp0.attr,
324{ 503 &dev_attr_otp1.attr,
325 return sysfs_show_reg(dev, attr, buf, 504 &dev_attr_otp2.attr,
326 AD525X_I2C_EEPROM | AD525X_TOL_RDAC3); 505 &dev_attr_otp3.attr,
327} 506 &dev_attr_otp4.attr,
507 &dev_attr_otp5.attr,
508 NULL
509};
328 510
329static DEVICE_ATTR(tolerance3, S_IRUGO, show_tolerance3, NULL); 511static const struct attribute *dpot_attrib_otp_en[] = {
330 512 &dev_attr_otp0en.attr,
331static struct attribute *ad525x_attributes_wipers[4][4] = { 513 &dev_attr_otp1en.attr,
332 { 514 &dev_attr_otp2en.attr,
333 &dev_attr_rdac0.attr, 515 &dev_attr_otp3en.attr,
334 &dev_attr_eeprom0.attr, 516 &dev_attr_otp4en.attr,
335 &dev_attr_tolerance0.attr, 517 &dev_attr_otp5en.attr,
336 NULL 518 NULL
337 }, {
338 &dev_attr_rdac1.attr,
339 &dev_attr_eeprom1.attr,
340 &dev_attr_tolerance1.attr,
341 NULL
342 }, {
343 &dev_attr_rdac2.attr,
344 &dev_attr_eeprom2.attr,
345 &dev_attr_tolerance2.attr,
346 NULL
347 }, {
348 &dev_attr_rdac3.attr,
349 &dev_attr_eeprom3.attr,
350 &dev_attr_tolerance3.attr,
351 NULL
352 }
353}; 519};
354 520
355static const struct attribute_group ad525x_group_wipers[] = { 521static const struct attribute *dpot_attrib_tolerance[] = {
356 {.attrs = ad525x_attributes_wipers[AD525X_RDAC0]}, 522 &dev_attr_tolerance0.attr,
357 {.attrs = ad525x_attributes_wipers[AD525X_RDAC1]}, 523 &dev_attr_tolerance1.attr,
358 {.attrs = ad525x_attributes_wipers[AD525X_RDAC2]}, 524 &dev_attr_tolerance2.attr,
359 {.attrs = ad525x_attributes_wipers[AD525X_RDAC3]}, 525 &dev_attr_tolerance3.attr,
526 &dev_attr_tolerance4.attr,
527 &dev_attr_tolerance5.attr,
528 NULL
360}; 529};
361 530
362/* ------------------------------------------------------------------------- */ 531/* ------------------------------------------------------------------------- */
363 532
364static ssize_t set_inc_all(struct device *dev, 533#define DPOT_DEVICE_DO_CMD(_name, _cmd) static ssize_t \
365 struct device_attribute *attr, 534set_##_name(struct device *dev, \
366 const char *buf, size_t count) 535 struct device_attribute *attr, \
367{ 536 const char *buf, size_t count) \
368 return sysfs_do_cmd(dev, attr, buf, count, AD525X_INC_ALL); 537{ \
369} 538 return sysfs_do_cmd(dev, attr, buf, count, _cmd); \
539} \
540static DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, NULL, set_##_name);
370 541
371static DEVICE_ATTR(inc_all, S_IWUSR, NULL, set_inc_all); 542DPOT_DEVICE_DO_CMD(inc_all, DPOT_INC_ALL);
372 543DPOT_DEVICE_DO_CMD(dec_all, DPOT_DEC_ALL);
373static ssize_t set_dec_all(struct device *dev, 544DPOT_DEVICE_DO_CMD(inc_all_6db, DPOT_INC_ALL_6DB);
374 struct device_attribute *attr, 545DPOT_DEVICE_DO_CMD(dec_all_6db, DPOT_DEC_ALL_6DB);
375 const char *buf, size_t count)
376{
377 return sysfs_do_cmd(dev, attr, buf, count, AD525X_DEC_ALL);
378}
379
380static DEVICE_ATTR(dec_all, S_IWUSR, NULL, set_dec_all);
381
382static ssize_t set_inc_all_6db(struct device *dev,
383 struct device_attribute *attr,
384 const char *buf, size_t count)
385{
386 return sysfs_do_cmd(dev, attr, buf, count, AD525X_INC_ALL_6DB);
387}
388
389static DEVICE_ATTR(inc_all_6db, S_IWUSR, NULL, set_inc_all_6db);
390
391static ssize_t set_dec_all_6db(struct device *dev,
392 struct device_attribute *attr,
393 const char *buf, size_t count)
394{
395 return sysfs_do_cmd(dev, attr, buf, count, AD525X_DEC_ALL_6DB);
396}
397
398static DEVICE_ATTR(dec_all_6db, S_IWUSR, NULL, set_dec_all_6db);
399 546
400static struct attribute *ad525x_attributes_commands[] = { 547static struct attribute *ad525x_attributes_commands[] = {
401 &dev_attr_inc_all.attr, 548 &dev_attr_inc_all.attr,
@@ -409,74 +556,56 @@ static const struct attribute_group ad525x_group_commands = {
409 .attrs = ad525x_attributes_commands, 556 .attrs = ad525x_attributes_commands,
410}; 557};
411 558
412/* ------------------------------------------------------------------------- */ 559__devinit int ad_dpot_add_files(struct device *dev,
413 560 unsigned features, unsigned rdac)
414/* i2c device functions */ 561{
562 int err = sysfs_create_file(&dev->kobj,
563 dpot_attrib_wipers[rdac]);
564 if (features & F_CMD_EEP)
565 err |= sysfs_create_file(&dev->kobj,
566 dpot_attrib_eeprom[rdac]);
567 if (features & F_CMD_TOL)
568 err |= sysfs_create_file(&dev->kobj,
569 dpot_attrib_tolerance[rdac]);
570 if (features & F_CMD_OTP) {
571 err |= sysfs_create_file(&dev->kobj,
572 dpot_attrib_otp_en[rdac]);
573 err |= sysfs_create_file(&dev->kobj,
574 dpot_attrib_otp[rdac]);
575 }
415 576
416/** 577 if (err)
417 * ad525x_read - return the value contained in the specified register 578 dev_err(dev, "failed to register sysfs hooks for RDAC%d\n",
418 * on the AD5258 device. 579 rdac);
419 * @client: value returned from i2c_new_device()
420 * @reg: the register to read
421 *
422 * If the tolerance register is specified, 2 bytes are returned.
423 * Otherwise, 1 byte is returned. A negative value indicates an error
424 * occurred while reading the register.
425 */
426static s32 ad525x_read(struct i2c_client *client, u8 reg)
427{
428 struct dpot_data *data = i2c_get_clientdata(client);
429 580
430 if ((reg & AD525X_REG_TOL) || (data->max_pos > 256)) 581 return err;
431 return i2c_smbus_read_word_data(client, (reg & 0xF8) |
432 ((reg & 0x7) << 1));
433 else
434 return i2c_smbus_read_byte_data(client, reg);
435} 582}
436 583
437/** 584inline void ad_dpot_remove_files(struct device *dev,
438 * ad525x_write - store the given value in the specified register on 585 unsigned features, unsigned rdac)
439 * the AD5258 device. 586{
440 * @client: value returned from i2c_new_device() 587 sysfs_remove_file(&dev->kobj,
441 * @reg: the register to write 588 dpot_attrib_wipers[rdac]);
442 * @value: the byte to store in the register 589 if (features & F_CMD_EEP)
443 * 590 sysfs_remove_file(&dev->kobj,
444 * For certain instructions that do not require a data byte, "NULL" 591 dpot_attrib_eeprom[rdac]);
445 * should be specified for the "value" parameter. These instructions 592 if (features & F_CMD_TOL)
446 * include NOP, RESTORE_FROM_EEPROM, and STORE_TO_EEPROM. 593 sysfs_remove_file(&dev->kobj,
447 * 594 dpot_attrib_tolerance[rdac]);
448 * A negative return value indicates an error occurred while reading 595 if (features & F_CMD_OTP) {
449 * the register. 596 sysfs_remove_file(&dev->kobj,
450 */ 597 dpot_attrib_otp_en[rdac]);
451static s32 ad525x_write(struct i2c_client *client, u8 reg, u8 value) 598 sysfs_remove_file(&dev->kobj,
452{ 599 dpot_attrib_otp[rdac]);
453 struct dpot_data *data = i2c_get_clientdata(client); 600 }
454
455 /* Only write the instruction byte for certain commands */
456 if (reg & AD525X_I2C_CMD)
457 return i2c_smbus_write_byte(client, reg);
458
459 if (data->max_pos > 256)
460 return i2c_smbus_write_word_data(client, (reg & 0xF8) |
461 ((reg & 0x7) << 1), value);
462 else
463 /* All other registers require instruction + data bytes */
464 return i2c_smbus_write_byte_data(client, reg, value);
465} 601}
466 602
467static int ad525x_probe(struct i2c_client *client, 603__devinit int ad_dpot_probe(struct device *dev,
468 const struct i2c_device_id *id) 604 struct ad_dpot_bus_data *bdata, const struct ad_dpot_id *id)
469{ 605{
470 struct device *dev = &client->dev;
471 struct dpot_data *data;
472 int err = 0;
473 606
474 dev_dbg(dev, "%s\n", __func__); 607 struct dpot_data *data;
475 608 int i, err = 0;
476 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) {
477 dev_err(dev, "missing I2C functionality for this driver\n");
478 goto exit;
479 }
480 609
481 data = kzalloc(sizeof(struct dpot_data), GFP_KERNEL); 610 data = kzalloc(sizeof(struct dpot_data), GFP_KERNEL);
482 if (!data) { 611 if (!data) {
@@ -484,183 +613,74 @@ static int ad525x_probe(struct i2c_client *client,
484 goto exit; 613 goto exit;
485 } 614 }
486 615
487 i2c_set_clientdata(client, data); 616 dev_set_drvdata(dev, data);
488 mutex_init(&data->update_lock); 617 mutex_init(&data->update_lock);
489 618
490 switch (id->driver_data) { 619 data->bdata = *bdata;
491 case AD5258_ID: 620 data->devid = id->devid;
492 data->max_pos = AD5258_MAX_POSITION; 621
493 err = sysfs_create_group(&dev->kobj, 622 data->max_pos = 1 << DPOT_MAX_POS(data->devid);
494 &ad525x_group_wipers[AD525X_RDAC0]); 623 data->rdac_mask = data->max_pos - 1;
495 break; 624 data->feat = DPOT_FEAT(data->devid);
496 case AD5259_ID: 625 data->uid = DPOT_UID(data->devid);
497 data->max_pos = AD5259_MAX_POSITION; 626 data->wipers = DPOT_WIPERS(data->devid);
498 err = sysfs_create_group(&dev->kobj, 627
499 &ad525x_group_wipers[AD525X_RDAC0]); 628 for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
500 break; 629 if (data->wipers & (1 << i)) {
501 case AD5251_ID: 630 err = ad_dpot_add_files(dev, data->feat, i);
502 data->max_pos = AD5251_MAX_POSITION; 631 if (err)
503 err = sysfs_create_group(&dev->kobj, 632 goto exit_remove_files;
504 &ad525x_group_wipers[AD525X_RDAC1]); 633 /* power-up midscale */
505 err |= sysfs_create_group(&dev->kobj, 634 if (data->feat & F_RDACS_WONLY)
506 &ad525x_group_wipers[AD525X_RDAC3]); 635 data->rdac_cache[i] = data->max_pos / 2;
507 err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands); 636 }
508 break; 637
509 case AD5252_ID: 638 if (data->feat & F_CMD_INC)
510 data->max_pos = AD5252_MAX_POSITION; 639 err = sysfs_create_group(&dev->kobj, &ad525x_group_commands);
511 err = sysfs_create_group(&dev->kobj,
512 &ad525x_group_wipers[AD525X_RDAC1]);
513 err |= sysfs_create_group(&dev->kobj,
514 &ad525x_group_wipers[AD525X_RDAC3]);
515 err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands);
516 break;
517 case AD5253_ID:
518 data->max_pos = AD5253_MAX_POSITION;
519 err = sysfs_create_group(&dev->kobj,
520 &ad525x_group_wipers[AD525X_RDAC0]);
521 err |= sysfs_create_group(&dev->kobj,
522 &ad525x_group_wipers[AD525X_RDAC1]);
523 err |= sysfs_create_group(&dev->kobj,
524 &ad525x_group_wipers[AD525X_RDAC2]);
525 err |= sysfs_create_group(&dev->kobj,
526 &ad525x_group_wipers[AD525X_RDAC3]);
527 err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands);
528 break;
529 case AD5254_ID:
530 data->max_pos = AD5254_MAX_POSITION;
531 err = sysfs_create_group(&dev->kobj,
532 &ad525x_group_wipers[AD525X_RDAC0]);
533 err |= sysfs_create_group(&dev->kobj,
534 &ad525x_group_wipers[AD525X_RDAC1]);
535 err |= sysfs_create_group(&dev->kobj,
536 &ad525x_group_wipers[AD525X_RDAC2]);
537 err |= sysfs_create_group(&dev->kobj,
538 &ad525x_group_wipers[AD525X_RDAC3]);
539 err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands);
540 break;
541 case AD5255_ID:
542 data->max_pos = AD5255_MAX_POSITION;
543 err = sysfs_create_group(&dev->kobj,
544 &ad525x_group_wipers[AD525X_RDAC0]);
545 err |= sysfs_create_group(&dev->kobj,
546 &ad525x_group_wipers[AD525X_RDAC1]);
547 err |= sysfs_create_group(&dev->kobj,
548 &ad525x_group_wipers[AD525X_RDAC2]);
549 err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands);
550 break;
551 default:
552 err = -ENODEV;
553 goto exit_free;
554 }
555 640
556 if (err) { 641 if (err) {
557 dev_err(dev, "failed to register sysfs hooks\n"); 642 dev_err(dev, "failed to register sysfs hooks\n");
558 goto exit_free; 643 goto exit_free;
559 } 644 }
560 645
561 data->devid = id->driver_data;
562 data->rdac_mask = data->max_pos - 1;
563
564 dev_info(dev, "%s %d-Position Digital Potentiometer registered\n", 646 dev_info(dev, "%s %d-Position Digital Potentiometer registered\n",
565 id->name, data->max_pos); 647 id->name, data->max_pos);
566 648
567 return 0; 649 return 0;
568 650
651exit_remove_files:
652 for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
653 if (data->wipers & (1 << i))
654 ad_dpot_remove_files(dev, data->feat, i);
655
569exit_free: 656exit_free:
570 kfree(data); 657 kfree(data);
571 i2c_set_clientdata(client, NULL); 658 dev_set_drvdata(dev, NULL);
572exit: 659exit:
573 dev_err(dev, "failed to create client\n"); 660 dev_err(dev, "failed to create client for %s ID 0x%lX\n",
661 id->name, id->devid);
574 return err; 662 return err;
575} 663}
664EXPORT_SYMBOL(ad_dpot_probe);
576 665
577static int __devexit ad525x_remove(struct i2c_client *client) 666__devexit int ad_dpot_remove(struct device *dev)
578{ 667{
579 struct dpot_data *data = i2c_get_clientdata(client); 668 struct dpot_data *data = dev_get_drvdata(dev);
580 struct device *dev = &client->dev; 669 int i;
581 670
582 switch (data->devid) { 671 for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
583 case AD5258_ID: 672 if (data->wipers & (1 << i))
584 case AD5259_ID: 673 ad_dpot_remove_files(dev, data->feat, i);
585 sysfs_remove_group(&dev->kobj,
586 &ad525x_group_wipers[AD525X_RDAC0]);
587 break;
588 case AD5251_ID:
589 case AD5252_ID:
590 sysfs_remove_group(&dev->kobj,
591 &ad525x_group_wipers[AD525X_RDAC1]);
592 sysfs_remove_group(&dev->kobj,
593 &ad525x_group_wipers[AD525X_RDAC3]);
594 sysfs_remove_group(&dev->kobj, &ad525x_group_commands);
595 break;
596 case AD5253_ID:
597 case AD5254_ID:
598 sysfs_remove_group(&dev->kobj,
599 &ad525x_group_wipers[AD525X_RDAC0]);
600 sysfs_remove_group(&dev->kobj,
601 &ad525x_group_wipers[AD525X_RDAC1]);
602 sysfs_remove_group(&dev->kobj,
603 &ad525x_group_wipers[AD525X_RDAC2]);
604 sysfs_remove_group(&dev->kobj,
605 &ad525x_group_wipers[AD525X_RDAC3]);
606 sysfs_remove_group(&dev->kobj, &ad525x_group_commands);
607 break;
608 case AD5255_ID:
609 sysfs_remove_group(&dev->kobj,
610 &ad525x_group_wipers[AD525X_RDAC0]);
611 sysfs_remove_group(&dev->kobj,
612 &ad525x_group_wipers[AD525X_RDAC1]);
613 sysfs_remove_group(&dev->kobj,
614 &ad525x_group_wipers[AD525X_RDAC2]);
615 sysfs_remove_group(&dev->kobj, &ad525x_group_commands);
616 break;
617 }
618 674
619 i2c_set_clientdata(client, NULL);
620 kfree(data); 675 kfree(data);
621 676
622 return 0; 677 return 0;
623} 678}
679EXPORT_SYMBOL(ad_dpot_remove);
624 680
625static const struct i2c_device_id ad525x_idtable[] = {
626 {"ad5258", AD5258_ID},
627 {"ad5259", AD5259_ID},
628 {"ad5251", AD5251_ID},
629 {"ad5252", AD5252_ID},
630 {"ad5253", AD5253_ID},
631 {"ad5254", AD5254_ID},
632 {"ad5255", AD5255_ID},
633 {}
634};
635
636MODULE_DEVICE_TABLE(i2c, ad525x_idtable);
637
638static struct i2c_driver ad525x_driver = {
639 .driver = {
640 .owner = THIS_MODULE,
641 .name = DRIVER_NAME,
642 },
643 .id_table = ad525x_idtable,
644 .probe = ad525x_probe,
645 .remove = __devexit_p(ad525x_remove),
646};
647
648static int __init ad525x_init(void)
649{
650 return i2c_add_driver(&ad525x_driver);
651}
652
653module_init(ad525x_init);
654
655static void __exit ad525x_exit(void)
656{
657 i2c_del_driver(&ad525x_driver);
658}
659
660module_exit(ad525x_exit);
661 681
662MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>, " 682MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>, "
663 "Michael Hennerich <hennerich@blackfin.uclinux.org>, "); 683 "Michael Hennerich <hennerich@blackfin.uclinux.org>");
664MODULE_DESCRIPTION("AD5258/9 digital potentiometer driver"); 684MODULE_DESCRIPTION("Digital potentiometer driver");
665MODULE_LICENSE("GPL"); 685MODULE_LICENSE("GPL");
666MODULE_VERSION(DRIVER_VERSION); 686MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/misc/ad525x_dpot.h b/drivers/misc/ad525x_dpot.h
new file mode 100644
index 000000000000..78b89fd2e2fd
--- /dev/null
+++ b/drivers/misc/ad525x_dpot.h
@@ -0,0 +1,202 @@
1/*
2 * Driver for the Analog Devices digital potentiometers
3 *
4 * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#ifndef _AD_DPOT_H_
10#define _AD_DPOT_H_
11
12#include <linux/types.h>
13
14#define DPOT_CONF(features, wipers, max_pos, uid) \
15 (((features) << 18) | (((wipers) & 0xFF) << 10) | \
16 ((max_pos & 0xF) << 6) | (uid & 0x3F))
17
18#define DPOT_UID(conf) (conf & 0x3F)
19#define DPOT_MAX_POS(conf) ((conf >> 6) & 0xF)
20#define DPOT_WIPERS(conf) ((conf >> 10) & 0xFF)
21#define DPOT_FEAT(conf) (conf >> 18)
22
23#define BRDAC0 (1 << 0)
24#define BRDAC1 (1 << 1)
25#define BRDAC2 (1 << 2)
26#define BRDAC3 (1 << 3)
27#define BRDAC4 (1 << 4)
28#define BRDAC5 (1 << 5)
29#define MAX_RDACS 6
30
31#define F_CMD_INC (1 << 0) /* Features INC/DEC ALL, 6dB */
32#define F_CMD_EEP (1 << 1) /* Features EEPROM */
33#define F_CMD_OTP (1 << 2) /* Features OTP */
34#define F_CMD_TOL (1 << 3) /* RDACS feature Tolerance REG */
35#define F_RDACS_RW (1 << 4) /* RDACS are Read/Write */
36#define F_RDACS_WONLY (1 << 5) /* RDACS are Write only */
37#define F_AD_APPDATA (1 << 6) /* RDAC Address append to data */
38#define F_SPI_8BIT (1 << 7) /* All SPI XFERS are 8-bit */
39#define F_SPI_16BIT (1 << 8) /* All SPI XFERS are 16-bit */
40#define F_SPI_24BIT (1 << 9) /* All SPI XFERS are 24-bit */
41
42#define F_RDACS_RW_TOL (F_RDACS_RW | F_CMD_EEP | F_CMD_TOL)
43#define F_RDACS_RW_EEP (F_RDACS_RW | F_CMD_EEP)
44#define F_SPI (F_SPI_8BIT | F_SPI_16BIT | F_SPI_24BIT)
45
46enum dpot_devid {
47 AD5258_ID = DPOT_CONF(F_RDACS_RW_TOL, BRDAC0, 6, 0), /* I2C */
48 AD5259_ID = DPOT_CONF(F_RDACS_RW_TOL, BRDAC0, 8, 1),
49 AD5251_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
50 BRDAC0 | BRDAC3, 6, 2),
51 AD5252_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
52 BRDAC0 | BRDAC3, 8, 3),
53 AD5253_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
54 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 6, 4),
55 AD5254_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
56 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 8, 5),
57 AD5255_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
58 BRDAC0 | BRDAC1 | BRDAC2, 9, 6),
59 AD5160_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
60 BRDAC0, 8, 7), /* SPI */
61 AD5161_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
62 BRDAC0, 8, 8),
63 AD5162_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
64 BRDAC0 | BRDAC1, 8, 9),
65 AD5165_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
66 BRDAC0, 8, 10),
67 AD5200_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
68 BRDAC0, 8, 11),
69 AD5201_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
70 BRDAC0, 5, 12),
71 AD5203_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
72 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 6, 13),
73 AD5204_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
74 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 8, 14),
75 AD5206_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
76 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3 | BRDAC4 | BRDAC5,
77 8, 15),
78 AD5207_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
79 BRDAC0 | BRDAC1, 8, 16),
80 AD5231_ID = DPOT_CONF(F_RDACS_RW_EEP | F_CMD_INC | F_SPI_24BIT,
81 BRDAC0, 10, 17),
82 AD5232_ID = DPOT_CONF(F_RDACS_RW_EEP | F_CMD_INC | F_SPI_16BIT,
83 BRDAC0 | BRDAC1, 8, 18),
84 AD5233_ID = DPOT_CONF(F_RDACS_RW_EEP | F_CMD_INC | F_SPI_16BIT,
85 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 6, 19),
86 AD5235_ID = DPOT_CONF(F_RDACS_RW_EEP | F_CMD_INC | F_SPI_24BIT,
87 BRDAC0 | BRDAC1, 10, 20),
88 AD5260_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
89 BRDAC0, 8, 21),
90 AD5262_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
91 BRDAC0 | BRDAC1, 8, 22),
92 AD5263_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
93 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 8, 23),
94 AD5290_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
95 BRDAC0, 8, 24),
96 AD5291_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 8, 25),
97 AD5292_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 26),
98 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,
100 BRDAC0, 7, 28),
101 AD8400_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
102 BRDAC0, 8, 29),
103 AD8402_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
104 BRDAC0 | BRDAC1, 8, 30),
105 AD8403_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
106 BRDAC0 | BRDAC1 | BRDAC2, 8, 31),
107 ADN2850_ID = DPOT_CONF(F_RDACS_RW_EEP | F_CMD_INC | F_SPI_24BIT,
108 BRDAC0 | BRDAC1, 10, 32),
109 AD5241_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 8, 33),
110 AD5242_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 34),
111 AD5243_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 35),
112 AD5245_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 8, 36),
113 AD5246_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 7, 37),
114 AD5247_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 7, 38),
115 AD5248_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 39),
116 AD5280_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 8, 40),
117 AD5282_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 41),
118 ADN2860_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
119 BRDAC0 | BRDAC1 | BRDAC2, 9, 42),
120 AD5273_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 6, 43),
121 AD5171_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 6, 44),
122 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),
124 AD5173_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 47),
125};
126
127#define DPOT_RDAC0 0
128#define DPOT_RDAC1 1
129#define DPOT_RDAC2 2
130#define DPOT_RDAC3 3
131#define DPOT_RDAC4 4
132#define DPOT_RDAC5 5
133
134#define DPOT_RDAC_MASK 0x1F
135
136#define DPOT_REG_TOL 0x18
137#define DPOT_TOL_RDAC0 (DPOT_REG_TOL | DPOT_RDAC0)
138#define DPOT_TOL_RDAC1 (DPOT_REG_TOL | DPOT_RDAC1)
139#define DPOT_TOL_RDAC2 (DPOT_REG_TOL | DPOT_RDAC2)
140#define DPOT_TOL_RDAC3 (DPOT_REG_TOL | DPOT_RDAC3)
141#define DPOT_TOL_RDAC4 (DPOT_REG_TOL | DPOT_RDAC4)
142#define DPOT_TOL_RDAC5 (DPOT_REG_TOL | DPOT_RDAC5)
143
144/* RDAC-to-EEPROM Interface Commands */
145#define DPOT_ADDR_RDAC (0x0 << 5)
146#define DPOT_ADDR_EEPROM (0x1 << 5)
147#define DPOT_ADDR_OTP (0x1 << 6)
148#define DPOT_ADDR_CMD (0x1 << 7)
149#define DPOT_ADDR_OTP_EN (0x1 << 9)
150
151#define DPOT_DEC_ALL_6DB (DPOT_ADDR_CMD | (0x4 << 3))
152#define DPOT_INC_ALL_6DB (DPOT_ADDR_CMD | (0x9 << 3))
153#define DPOT_DEC_ALL (DPOT_ADDR_CMD | (0x6 << 3))
154#define DPOT_INC_ALL (DPOT_ADDR_CMD | (0xB << 3))
155
156#define DPOT_SPI_RDAC 0xB0
157#define DPOT_SPI_EEPROM 0x30
158#define DPOT_SPI_READ_RDAC 0xA0
159#define DPOT_SPI_READ_EEPROM 0x90
160#define DPOT_SPI_DEC_ALL_6DB 0x50
161#define DPOT_SPI_INC_ALL_6DB 0xD0
162#define DPOT_SPI_DEC_ALL 0x70
163#define DPOT_SPI_INC_ALL 0xF0
164
165/* AD5291/2/3 use special commands */
166#define DPOT_AD5291_RDAC 0x01
167#define DPOT_AD5291_READ_RDAC 0x02
168
169/* AD524x use special commands */
170#define DPOT_AD5291_RDAC_AB 0x80
171
172#define DPOT_AD5273_FUSE 0x80
173#define DPOT_AD5270_2_3_FUSE 0x20
174#define DPOT_AD5270_2_3_OW 0x08
175#define DPOT_AD5272_3_A0 0x08
176#define DPOT_AD5270_2FUSE 0x80
177
178struct dpot_data;
179
180struct ad_dpot_bus_ops {
181 int (*read_d8) (void *client);
182 int (*read_r8d8) (void *client, u8 reg);
183 int (*read_r8d16) (void *client, u8 reg);
184 int (*write_d8) (void *client, u8 val);
185 int (*write_r8d8) (void *client, u8 reg, u8 val);
186 int (*write_r8d16) (void *client, u8 reg, u16 val);
187};
188
189struct ad_dpot_bus_data {
190 void *client;
191 const struct ad_dpot_bus_ops *bops;
192};
193
194struct ad_dpot_id {
195 char *name;
196 unsigned long devid;
197};
198
199int ad_dpot_probe(struct device *dev, struct ad_dpot_bus_data *bdata, const struct ad_dpot_id *id);
200int ad_dpot_remove(struct device *dev);
201
202#endif