diff options
author | Paul Cercueil <paul.cercueil@analog.com> | 2016-04-05 03:46:19 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2016-04-10 09:29:06 -0400 |
commit | 56ca9db862bf3d78e279d424b3434d66617c27ae (patch) | |
tree | 17bb8afecced84e47b38c468eae026d306090d95 | |
parent | 5ea9274b8613f87120bfa6b0c0abc384c26cefb9 (diff) |
iio: dac: Add support for the AD5592R/AD5593R ADCs/DACs
This patch adds support for the AD5592R (spi) and AD5593R (i2c)
ADC/DAC/GPIO devices.
Signed-off-by: Paul Cercueil <paul.cercueil@analog.com>
Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r-- | Documentation/devicetree/bindings/iio/dac/ad5592r.txt | 155 | ||||
-rw-r--r-- | drivers/iio/dac/Kconfig | 27 | ||||
-rw-r--r-- | drivers/iio/dac/Makefile | 3 | ||||
-rw-r--r-- | drivers/iio/dac/ad5592r-base.c | 691 | ||||
-rw-r--r-- | drivers/iio/dac/ad5592r-base.h | 76 | ||||
-rw-r--r-- | drivers/iio/dac/ad5592r.c | 164 | ||||
-rw-r--r-- | drivers/iio/dac/ad5593r.c | 131 | ||||
-rw-r--r-- | include/dt-bindings/iio/adi,ad5592r.h | 16 |
8 files changed, 1263 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/iio/dac/ad5592r.txt b/Documentation/devicetree/bindings/iio/dac/ad5592r.txt new file mode 100644 index 000000000000..989f96f31c66 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/dac/ad5592r.txt | |||
@@ -0,0 +1,155 @@ | |||
1 | Analog Devices AD5592R/AD5593R DAC/ADC device driver | ||
2 | |||
3 | Required properties for the AD5592R: | ||
4 | - compatible: Must be "adi,ad5592r" | ||
5 | - reg: SPI chip select number for the device | ||
6 | - spi-max-frequency: Max SPI frequency to use (< 30000000) | ||
7 | - spi-cpol: The AD5592R requires inverse clock polarity (CPOL) mode | ||
8 | |||
9 | Required properties for the AD5593R: | ||
10 | - compatible: Must be "adi,ad5593r" | ||
11 | - reg: I2C address of the device | ||
12 | |||
13 | Required properties for all supported chips: | ||
14 | - #address-cells: Should be 1. | ||
15 | - #size-cells: Should be 0. | ||
16 | - channel nodes: | ||
17 | Each child node represents one channel and has the following | ||
18 | Required properties: | ||
19 | * reg: Pin on which this channel is connected to. | ||
20 | * adi,mode: Mode or function of this channel. | ||
21 | Macros specifying the valid values | ||
22 | can be found in <dt-bindings/iio/adi,ad5592r.h>. | ||
23 | |||
24 | The following values are currently supported: | ||
25 | * CH_MODE_UNUSED (the pin is unused) | ||
26 | * CH_MODE_ADC (the pin is ADC input) | ||
27 | * CH_MODE_DAC (the pin is DAC output) | ||
28 | * CH_MODE_DAC_AND_ADC (the pin is DAC output | ||
29 | but can be monitored by an ADC, since | ||
30 | there is no disadvantage this | ||
31 | this should be considered as the | ||
32 | preferred DAC mode) | ||
33 | * CH_MODE_GPIO (the pin is registered | ||
34 | with GPIOLIB) | ||
35 | Optional properties: | ||
36 | * adi,off-state: State of this channel when unused or the | ||
37 | device gets removed. Macros specifying the | ||
38 | valid values can be found in | ||
39 | <dt-bindings/iio/adi,ad5592r.h>. | ||
40 | |||
41 | * CH_OFFSTATE_PULLDOWN (the pin is pulled down) | ||
42 | * CH_OFFSTATE_OUT_LOW (the pin is output low) | ||
43 | * CH_OFFSTATE_OUT_HIGH (the pin is output high) | ||
44 | * CH_OFFSTATE_OUT_TRISTATE (the pin is | ||
45 | tristated output) | ||
46 | |||
47 | |||
48 | Optional properties: | ||
49 | - vref-supply: Phandle to the external reference voltage supply. This should | ||
50 | only be set if there is an external reference voltage connected to the VREF | ||
51 | pin. If the property is not set the internal 2.5V reference is used. | ||
52 | - reset-gpios : GPIO spec for the RESET pin. If specified, it will be | ||
53 | asserted during driver probe. | ||
54 | - gpio-controller: Marks the device node as a GPIO controller. | ||
55 | - #gpio-cells: Should be 2. The first cell is the GPIO number and the second | ||
56 | cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>. | ||
57 | |||
58 | AD5592R Example: | ||
59 | |||
60 | #include <dt-bindings/iio/adi,ad5592r.h> | ||
61 | |||
62 | vref: regulator-vref { | ||
63 | compatible = "regulator-fixed"; | ||
64 | regulator-name = "vref-ad559x"; | ||
65 | regulator-min-microvolt = <3300000>; | ||
66 | regulator-max-microvolt = <3300000>; | ||
67 | regulator-always-on; | ||
68 | }; | ||
69 | |||
70 | ad5592r@0 { | ||
71 | #size-cells = <0>; | ||
72 | #address-cells = <1>; | ||
73 | #gpio-cells = <2>; | ||
74 | compatible = "adi,ad5592r"; | ||
75 | reg = <0>; | ||
76 | |||
77 | spi-max-frequency = <1000000>; | ||
78 | spi-cpol; | ||
79 | |||
80 | vref-supply = <&vref>; /* optional */ | ||
81 | reset-gpios = <&gpio0 86 0>; /* optional */ | ||
82 | gpio-controller; | ||
83 | |||
84 | channel@0 { | ||
85 | reg = <0>; | ||
86 | adi,mode = <CH_MODE_DAC>; | ||
87 | }; | ||
88 | channel@1 { | ||
89 | reg = <1>; | ||
90 | adi,mode = <CH_MODE_ADC>; | ||
91 | }; | ||
92 | channel@2 { | ||
93 | reg = <2>; | ||
94 | adi,mode = <CH_MODE_DAC_AND_ADC>; | ||
95 | }; | ||
96 | channel@3 { | ||
97 | reg = <3>; | ||
98 | adi,mode = <CH_MODE_DAC_AND_ADC>; | ||
99 | adi,off-state = <CH_OFFSTATE_PULLDOWN>; | ||
100 | }; | ||
101 | channel@4 { | ||
102 | reg = <4>; | ||
103 | adi,mode = <CH_MODE_UNUSED>; | ||
104 | adi,off-state = <CH_OFFSTATE_PULLDOWN>; | ||
105 | }; | ||
106 | channel@5 { | ||
107 | reg = <5>; | ||
108 | adi,mode = <CH_MODE_GPIO>; | ||
109 | adi,off-state = <CH_OFFSTATE_PULLDOWN>; | ||
110 | }; | ||
111 | channel@6 { | ||
112 | reg = <6>; | ||
113 | adi,mode = <CH_MODE_GPIO>; | ||
114 | adi,off-state = <CH_OFFSTATE_PULLDOWN>; | ||
115 | }; | ||
116 | channel@7 { | ||
117 | reg = <7>; | ||
118 | adi,mode = <CH_MODE_GPIO>; | ||
119 | adi,off-state = <CH_OFFSTATE_PULLDOWN>; | ||
120 | }; | ||
121 | }; | ||
122 | |||
123 | AD5593R Example: | ||
124 | |||
125 | #include <dt-bindings/iio/adi,ad5592r.h> | ||
126 | |||
127 | ad5593r@10 { | ||
128 | #size-cells = <0>; | ||
129 | #address-cells = <1>; | ||
130 | #gpio-cells = <2>; | ||
131 | compatible = "adi,ad5593r"; | ||
132 | reg = <0x10>; | ||
133 | gpio-controller; | ||
134 | |||
135 | channel@0 { | ||
136 | reg = <0>; | ||
137 | adi,mode = <CH_MODE_DAC>; | ||
138 | adi,off-state = <CH_OFFSTATE_PULLDOWN>; | ||
139 | }; | ||
140 | channel@1 { | ||
141 | reg = <1>; | ||
142 | adi,mode = <CH_MODE_ADC>; | ||
143 | adi,off-state = <CH_OFFSTATE_PULLDOWN>; | ||
144 | }; | ||
145 | channel@2 { | ||
146 | reg = <2>; | ||
147 | adi,mode = <CH_MODE_DAC_AND_ADC>; | ||
148 | adi,off-state = <CH_OFFSTATE_PULLDOWN>; | ||
149 | }; | ||
150 | channel@6 { | ||
151 | reg = <6>; | ||
152 | adi,mode = <CH_MODE_GPIO>; | ||
153 | adi,off-state = <CH_OFFSTATE_PULLDOWN>; | ||
154 | }; | ||
155 | }; | ||
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index 210db81ca144..61d5008bff5c 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig | |||
@@ -74,6 +74,33 @@ config AD5449 | |||
74 | To compile this driver as a module, choose M here: the | 74 | To compile this driver as a module, choose M here: the |
75 | module will be called ad5449. | 75 | module will be called ad5449. |
76 | 76 | ||
77 | config AD5592R_BASE | ||
78 | tristate | ||
79 | |||
80 | config AD5592R | ||
81 | tristate "Analog Devices AD5592R ADC/DAC driver" | ||
82 | depends on SPI_MASTER | ||
83 | select GPIOLIB | ||
84 | select AD5592R_BASE | ||
85 | help | ||
86 | Say yes here to build support for Analog Devices AD5592R | ||
87 | Digital to Analog / Analog to Digital Converter. | ||
88 | |||
89 | To compile this driver as a module, choose M here: the | ||
90 | module will be called ad5592r. | ||
91 | |||
92 | config AD5593R | ||
93 | tristate "Analog Devices AD5593R ADC/DAC driver" | ||
94 | depends on I2C | ||
95 | select GPIOLIB | ||
96 | select AD5592R_BASE | ||
97 | help | ||
98 | Say yes here to build support for Analog Devices AD5593R | ||
99 | Digital to Analog / Analog to Digital Converter. | ||
100 | |||
101 | To compile this driver as a module, choose M here: the | ||
102 | module will be called ad5593r. | ||
103 | |||
77 | config AD5504 | 104 | config AD5504 |
78 | tristate "Analog Devices AD5504/AD5501 DAC SPI driver" | 105 | tristate "Analog Devices AD5504/AD5501 DAC SPI driver" |
79 | depends on SPI | 106 | depends on SPI |
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 420a15cdaa53..8b78d5ca9b11 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile | |||
@@ -11,6 +11,9 @@ obj-$(CONFIG_AD5064) += ad5064.o | |||
11 | obj-$(CONFIG_AD5504) += ad5504.o | 11 | obj-$(CONFIG_AD5504) += ad5504.o |
12 | obj-$(CONFIG_AD5446) += ad5446.o | 12 | obj-$(CONFIG_AD5446) += ad5446.o |
13 | obj-$(CONFIG_AD5449) += ad5449.o | 13 | obj-$(CONFIG_AD5449) += ad5449.o |
14 | obj-$(CONFIG_AD5592R_BASE) += ad5592r-base.o | ||
15 | obj-$(CONFIG_AD5592R) += ad5592r.o | ||
16 | obj-$(CONFIG_AD5593R) += ad5593r.o | ||
14 | obj-$(CONFIG_AD5755) += ad5755.o | 17 | obj-$(CONFIG_AD5755) += ad5755.o |
15 | obj-$(CONFIG_AD5761) += ad5761.o | 18 | obj-$(CONFIG_AD5761) += ad5761.o |
16 | obj-$(CONFIG_AD5764) += ad5764.o | 19 | obj-$(CONFIG_AD5764) += ad5764.o |
diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c new file mode 100644 index 000000000000..948f600e7059 --- /dev/null +++ b/drivers/iio/dac/ad5592r-base.c | |||
@@ -0,0 +1,691 @@ | |||
1 | /* | ||
2 | * AD5592R Digital <-> Analog converters driver | ||
3 | * | ||
4 | * Copyright 2014-2016 Analog Devices Inc. | ||
5 | * Author: Paul Cercueil <paul.cercueil@analog.com> | ||
6 | * | ||
7 | * Licensed under the GPL-2. | ||
8 | */ | ||
9 | |||
10 | #include <linux/bitops.h> | ||
11 | #include <linux/delay.h> | ||
12 | #include <linux/iio/iio.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/mutex.h> | ||
15 | #include <linux/of.h> | ||
16 | #include <linux/regulator/consumer.h> | ||
17 | #include <linux/gpio/consumer.h> | ||
18 | #include <linux/gpio/driver.h> | ||
19 | #include <linux/gpio.h> | ||
20 | #include <linux/property.h> | ||
21 | |||
22 | #include <dt-bindings/iio/adi,ad5592r.h> | ||
23 | |||
24 | #include "ad5592r-base.h" | ||
25 | |||
26 | static int ad5592r_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
27 | { | ||
28 | struct ad5592r_state *st = gpiochip_get_data(chip); | ||
29 | int ret = 0; | ||
30 | u8 val; | ||
31 | |||
32 | mutex_lock(&st->gpio_lock); | ||
33 | |||
34 | if (st->gpio_out & BIT(offset)) | ||
35 | val = st->gpio_val; | ||
36 | else | ||
37 | ret = st->ops->gpio_read(st, &val); | ||
38 | |||
39 | mutex_unlock(&st->gpio_lock); | ||
40 | |||
41 | if (ret < 0) | ||
42 | return ret; | ||
43 | |||
44 | return !!(val & BIT(offset)); | ||
45 | } | ||
46 | |||
47 | static void ad5592r_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
48 | { | ||
49 | struct ad5592r_state *st = gpiochip_get_data(chip); | ||
50 | |||
51 | mutex_lock(&st->gpio_lock); | ||
52 | |||
53 | if (value) | ||
54 | st->gpio_val |= BIT(offset); | ||
55 | else | ||
56 | st->gpio_val &= ~BIT(offset); | ||
57 | |||
58 | st->ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val); | ||
59 | |||
60 | mutex_unlock(&st->gpio_lock); | ||
61 | } | ||
62 | |||
63 | static int ad5592r_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
64 | { | ||
65 | struct ad5592r_state *st = gpiochip_get_data(chip); | ||
66 | int ret; | ||
67 | |||
68 | mutex_lock(&st->gpio_lock); | ||
69 | |||
70 | st->gpio_out &= ~BIT(offset); | ||
71 | st->gpio_in |= BIT(offset); | ||
72 | |||
73 | ret = st->ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out); | ||
74 | if (ret < 0) | ||
75 | goto err_unlock; | ||
76 | |||
77 | ret = st->ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in); | ||
78 | |||
79 | err_unlock: | ||
80 | mutex_unlock(&st->gpio_lock); | ||
81 | |||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | static int ad5592r_gpio_direction_output(struct gpio_chip *chip, | ||
86 | unsigned offset, int value) | ||
87 | { | ||
88 | struct ad5592r_state *st = gpiochip_get_data(chip); | ||
89 | int ret; | ||
90 | |||
91 | mutex_lock(&st->gpio_lock); | ||
92 | |||
93 | if (value) | ||
94 | st->gpio_val |= BIT(offset); | ||
95 | else | ||
96 | st->gpio_val &= ~BIT(offset); | ||
97 | |||
98 | st->gpio_in &= ~BIT(offset); | ||
99 | st->gpio_out |= BIT(offset); | ||
100 | |||
101 | ret = st->ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val); | ||
102 | if (ret < 0) | ||
103 | goto err_unlock; | ||
104 | |||
105 | ret = st->ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out); | ||
106 | if (ret < 0) | ||
107 | goto err_unlock; | ||
108 | |||
109 | ret = st->ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in); | ||
110 | |||
111 | err_unlock: | ||
112 | mutex_unlock(&st->gpio_lock); | ||
113 | |||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | static int ad5592r_gpio_request(struct gpio_chip *chip, unsigned offset) | ||
118 | { | ||
119 | struct ad5592r_state *st = gpiochip_get_data(chip); | ||
120 | |||
121 | if (!(st->gpio_map & BIT(offset))) { | ||
122 | dev_err(st->dev, "GPIO %d is reserved by alternate function\n", | ||
123 | offset); | ||
124 | return -ENODEV; | ||
125 | } | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static int ad5592r_gpio_init(struct ad5592r_state *st) | ||
131 | { | ||
132 | if (!st->gpio_map) | ||
133 | return 0; | ||
134 | |||
135 | st->gpiochip.label = dev_name(st->dev); | ||
136 | st->gpiochip.base = -1; | ||
137 | st->gpiochip.ngpio = 8; | ||
138 | st->gpiochip.parent = st->dev; | ||
139 | st->gpiochip.can_sleep = true; | ||
140 | st->gpiochip.direction_input = ad5592r_gpio_direction_input; | ||
141 | st->gpiochip.direction_output = ad5592r_gpio_direction_output; | ||
142 | st->gpiochip.get = ad5592r_gpio_get; | ||
143 | st->gpiochip.set = ad5592r_gpio_set; | ||
144 | st->gpiochip.request = ad5592r_gpio_request; | ||
145 | st->gpiochip.owner = THIS_MODULE; | ||
146 | |||
147 | mutex_init(&st->gpio_lock); | ||
148 | |||
149 | return gpiochip_add_data(&st->gpiochip, st); | ||
150 | } | ||
151 | |||
152 | static void ad5592r_gpio_cleanup(struct ad5592r_state *st) | ||
153 | { | ||
154 | if (st->gpio_map) | ||
155 | gpiochip_remove(&st->gpiochip); | ||
156 | } | ||
157 | |||
158 | static int ad5592r_reset(struct ad5592r_state *st) | ||
159 | { | ||
160 | struct gpio_desc *gpio; | ||
161 | struct iio_dev *iio_dev = iio_priv_to_dev(st); | ||
162 | |||
163 | gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW); | ||
164 | if (IS_ERR(gpio)) | ||
165 | return PTR_ERR(gpio); | ||
166 | |||
167 | if (gpio) { | ||
168 | udelay(1); | ||
169 | gpiod_set_value(gpio, 1); | ||
170 | } else { | ||
171 | mutex_lock(&iio_dev->mlock); | ||
172 | /* Writing this magic value resets the device */ | ||
173 | st->ops->reg_write(st, AD5592R_REG_RESET, 0xdac); | ||
174 | mutex_unlock(&iio_dev->mlock); | ||
175 | } | ||
176 | |||
177 | udelay(250); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int ad5592r_get_vref(struct ad5592r_state *st) | ||
183 | { | ||
184 | int ret; | ||
185 | |||
186 | if (st->reg) { | ||
187 | ret = regulator_get_voltage(st->reg); | ||
188 | if (ret < 0) | ||
189 | return ret; | ||
190 | |||
191 | return ret / 1000; | ||
192 | } else { | ||
193 | return 2500; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | static int ad5592r_set_channel_modes(struct ad5592r_state *st) | ||
198 | { | ||
199 | const struct ad5592r_rw_ops *ops = st->ops; | ||
200 | int ret; | ||
201 | unsigned i; | ||
202 | struct iio_dev *iio_dev = iio_priv_to_dev(st); | ||
203 | u8 pulldown = 0, tristate = 0, dac = 0, adc = 0; | ||
204 | u16 read_back; | ||
205 | |||
206 | for (i = 0; i < st->num_channels; i++) { | ||
207 | switch (st->channel_modes[i]) { | ||
208 | case CH_MODE_DAC: | ||
209 | dac |= BIT(i); | ||
210 | break; | ||
211 | |||
212 | case CH_MODE_ADC: | ||
213 | adc |= BIT(i); | ||
214 | break; | ||
215 | |||
216 | case CH_MODE_DAC_AND_ADC: | ||
217 | dac |= BIT(i); | ||
218 | adc |= BIT(i); | ||
219 | break; | ||
220 | |||
221 | case CH_MODE_GPIO: | ||
222 | st->gpio_map |= BIT(i); | ||
223 | st->gpio_in |= BIT(i); /* Default to input */ | ||
224 | break; | ||
225 | |||
226 | case CH_MODE_UNUSED: | ||
227 | /* fall-through */ | ||
228 | default: | ||
229 | switch (st->channel_offstate[i]) { | ||
230 | case CH_OFFSTATE_OUT_TRISTATE: | ||
231 | tristate |= BIT(i); | ||
232 | break; | ||
233 | |||
234 | case CH_OFFSTATE_OUT_LOW: | ||
235 | st->gpio_out |= BIT(i); | ||
236 | break; | ||
237 | |||
238 | case CH_OFFSTATE_OUT_HIGH: | ||
239 | st->gpio_out |= BIT(i); | ||
240 | st->gpio_val |= BIT(i); | ||
241 | break; | ||
242 | |||
243 | case CH_OFFSTATE_PULLDOWN: | ||
244 | /* fall-through */ | ||
245 | default: | ||
246 | pulldown |= BIT(i); | ||
247 | break; | ||
248 | } | ||
249 | } | ||
250 | } | ||
251 | |||
252 | mutex_lock(&iio_dev->mlock); | ||
253 | |||
254 | /* Pull down unused pins to GND */ | ||
255 | ret = ops->reg_write(st, AD5592R_REG_PULLDOWN, pulldown); | ||
256 | if (ret) | ||
257 | goto err_unlock; | ||
258 | |||
259 | ret = ops->reg_write(st, AD5592R_REG_TRISTATE, tristate); | ||
260 | if (ret) | ||
261 | goto err_unlock; | ||
262 | |||
263 | /* Configure pins that we use */ | ||
264 | ret = ops->reg_write(st, AD5592R_REG_DAC_EN, dac); | ||
265 | if (ret) | ||
266 | goto err_unlock; | ||
267 | |||
268 | ret = ops->reg_write(st, AD5592R_REG_ADC_EN, adc); | ||
269 | if (ret) | ||
270 | goto err_unlock; | ||
271 | |||
272 | ret = ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val); | ||
273 | if (ret) | ||
274 | goto err_unlock; | ||
275 | |||
276 | ret = ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out); | ||
277 | if (ret) | ||
278 | goto err_unlock; | ||
279 | |||
280 | ret = ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in); | ||
281 | if (ret) | ||
282 | goto err_unlock; | ||
283 | |||
284 | /* Verify that we can read back at least one register */ | ||
285 | ret = ops->reg_read(st, AD5592R_REG_ADC_EN, &read_back); | ||
286 | if (!ret && (read_back & 0xff) != adc) | ||
287 | ret = -EIO; | ||
288 | |||
289 | err_unlock: | ||
290 | mutex_unlock(&iio_dev->mlock); | ||
291 | return ret; | ||
292 | } | ||
293 | |||
294 | static int ad5592r_reset_channel_modes(struct ad5592r_state *st) | ||
295 | { | ||
296 | int i; | ||
297 | |||
298 | for (i = 0; i < ARRAY_SIZE(st->channel_modes); i++) | ||
299 | st->channel_modes[i] = CH_MODE_UNUSED; | ||
300 | |||
301 | return ad5592r_set_channel_modes(st); | ||
302 | } | ||
303 | |||
304 | static int ad5592r_write_raw(struct iio_dev *iio_dev, | ||
305 | struct iio_chan_spec const *chan, int val, int val2, long mask) | ||
306 | { | ||
307 | struct ad5592r_state *st = iio_priv(iio_dev); | ||
308 | int ret; | ||
309 | |||
310 | switch (mask) { | ||
311 | case IIO_CHAN_INFO_RAW: | ||
312 | |||
313 | if (val >= (1 << chan->scan_type.realbits) || val < 0) | ||
314 | return -EINVAL; | ||
315 | |||
316 | if (!chan->output) | ||
317 | return -EINVAL; | ||
318 | |||
319 | mutex_lock(&iio_dev->mlock); | ||
320 | ret = st->ops->write_dac(st, chan->channel, val); | ||
321 | if (!ret) | ||
322 | st->cached_dac[chan->channel] = val; | ||
323 | mutex_unlock(&iio_dev->mlock); | ||
324 | return ret; | ||
325 | case IIO_CHAN_INFO_SCALE: | ||
326 | if (chan->type == IIO_VOLTAGE) { | ||
327 | bool gain; | ||
328 | |||
329 | if (val == st->scale_avail[0][0] && | ||
330 | val2 == st->scale_avail[0][1]) | ||
331 | gain = false; | ||
332 | else if (val == st->scale_avail[1][0] && | ||
333 | val2 == st->scale_avail[1][1]) | ||
334 | gain = true; | ||
335 | else | ||
336 | return -EINVAL; | ||
337 | |||
338 | mutex_lock(&iio_dev->mlock); | ||
339 | |||
340 | ret = st->ops->reg_read(st, AD5592R_REG_CTRL, | ||
341 | &st->cached_gp_ctrl); | ||
342 | if (ret < 0) { | ||
343 | mutex_unlock(&iio_dev->mlock); | ||
344 | return ret; | ||
345 | } | ||
346 | |||
347 | if (chan->output) { | ||
348 | if (gain) | ||
349 | st->cached_gp_ctrl |= | ||
350 | AD5592R_REG_CTRL_DAC_RANGE; | ||
351 | else | ||
352 | st->cached_gp_ctrl &= | ||
353 | ~AD5592R_REG_CTRL_DAC_RANGE; | ||
354 | } else { | ||
355 | if (gain) | ||
356 | st->cached_gp_ctrl |= | ||
357 | AD5592R_REG_CTRL_ADC_RANGE; | ||
358 | else | ||
359 | st->cached_gp_ctrl &= | ||
360 | ~AD5592R_REG_CTRL_ADC_RANGE; | ||
361 | } | ||
362 | |||
363 | ret = st->ops->reg_write(st, AD5592R_REG_CTRL, | ||
364 | st->cached_gp_ctrl); | ||
365 | mutex_unlock(&iio_dev->mlock); | ||
366 | |||
367 | return ret; | ||
368 | } | ||
369 | break; | ||
370 | default: | ||
371 | return -EINVAL; | ||
372 | } | ||
373 | |||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | static int ad5592r_read_raw(struct iio_dev *iio_dev, | ||
378 | struct iio_chan_spec const *chan, | ||
379 | int *val, int *val2, long m) | ||
380 | { | ||
381 | struct ad5592r_state *st = iio_priv(iio_dev); | ||
382 | u16 read_val; | ||
383 | int ret; | ||
384 | |||
385 | switch (m) { | ||
386 | case IIO_CHAN_INFO_RAW: | ||
387 | mutex_lock(&iio_dev->mlock); | ||
388 | |||
389 | if (!chan->output) { | ||
390 | ret = st->ops->read_adc(st, chan->channel, &read_val); | ||
391 | if (ret) | ||
392 | goto unlock; | ||
393 | |||
394 | if ((read_val >> 12 & 0x7) != (chan->channel & 0x7)) { | ||
395 | dev_err(st->dev, "Error while reading channel %u\n", | ||
396 | chan->channel); | ||
397 | ret = -EIO; | ||
398 | goto unlock; | ||
399 | } | ||
400 | |||
401 | read_val &= GENMASK(11, 0); | ||
402 | |||
403 | } else { | ||
404 | read_val = st->cached_dac[chan->channel]; | ||
405 | } | ||
406 | |||
407 | dev_dbg(st->dev, "Channel %u read: 0x%04hX\n", | ||
408 | chan->channel, read_val); | ||
409 | |||
410 | *val = (int) read_val; | ||
411 | ret = IIO_VAL_INT; | ||
412 | break; | ||
413 | case IIO_CHAN_INFO_SCALE: | ||
414 | *val = ad5592r_get_vref(st); | ||
415 | |||
416 | if (chan->type == IIO_TEMP) { | ||
417 | s64 tmp = *val * (3767897513LL / 25LL); | ||
418 | *val = div_s64_rem(tmp, 1000000000LL, val2); | ||
419 | |||
420 | ret = IIO_VAL_INT_PLUS_MICRO; | ||
421 | } else { | ||
422 | int mult; | ||
423 | |||
424 | mutex_lock(&iio_dev->mlock); | ||
425 | |||
426 | if (chan->output) | ||
427 | mult = !!(st->cached_gp_ctrl & | ||
428 | AD5592R_REG_CTRL_DAC_RANGE); | ||
429 | else | ||
430 | mult = !!(st->cached_gp_ctrl & | ||
431 | AD5592R_REG_CTRL_ADC_RANGE); | ||
432 | |||
433 | *val *= ++mult; | ||
434 | |||
435 | *val2 = chan->scan_type.realbits; | ||
436 | ret = IIO_VAL_FRACTIONAL_LOG2; | ||
437 | } | ||
438 | break; | ||
439 | case IIO_CHAN_INFO_OFFSET: | ||
440 | ret = ad5592r_get_vref(st); | ||
441 | |||
442 | mutex_lock(&iio_dev->mlock); | ||
443 | |||
444 | if (st->cached_gp_ctrl & AD5592R_REG_CTRL_ADC_RANGE) | ||
445 | *val = (-34365 * 25) / ret; | ||
446 | else | ||
447 | *val = (-75365 * 25) / ret; | ||
448 | ret = IIO_VAL_INT; | ||
449 | break; | ||
450 | default: | ||
451 | ret = -EINVAL; | ||
452 | } | ||
453 | |||
454 | unlock: | ||
455 | mutex_unlock(&iio_dev->mlock); | ||
456 | return ret; | ||
457 | } | ||
458 | |||
459 | static int ad5592r_write_raw_get_fmt(struct iio_dev *indio_dev, | ||
460 | struct iio_chan_spec const *chan, long mask) | ||
461 | { | ||
462 | switch (mask) { | ||
463 | case IIO_CHAN_INFO_SCALE: | ||
464 | return IIO_VAL_INT_PLUS_NANO; | ||
465 | |||
466 | default: | ||
467 | return IIO_VAL_INT_PLUS_MICRO; | ||
468 | } | ||
469 | |||
470 | return -EINVAL; | ||
471 | } | ||
472 | |||
473 | static const struct iio_info ad5592r_info = { | ||
474 | .read_raw = ad5592r_read_raw, | ||
475 | .write_raw = ad5592r_write_raw, | ||
476 | .write_raw_get_fmt = ad5592r_write_raw_get_fmt, | ||
477 | .driver_module = THIS_MODULE, | ||
478 | }; | ||
479 | |||
480 | static ssize_t ad5592r_show_scale_available(struct iio_dev *iio_dev, | ||
481 | uintptr_t private, | ||
482 | const struct iio_chan_spec *chan, | ||
483 | char *buf) | ||
484 | { | ||
485 | struct ad5592r_state *st = iio_priv(iio_dev); | ||
486 | |||
487 | return sprintf(buf, "%d.%09u %d.%09u\n", | ||
488 | st->scale_avail[0][0], st->scale_avail[0][1], | ||
489 | st->scale_avail[1][0], st->scale_avail[1][1]); | ||
490 | } | ||
491 | |||
492 | static struct iio_chan_spec_ext_info ad5592r_ext_info[] = { | ||
493 | { | ||
494 | .name = "scale_available", | ||
495 | .read = ad5592r_show_scale_available, | ||
496 | .shared = true, | ||
497 | }, | ||
498 | {}, | ||
499 | }; | ||
500 | |||
501 | static void ad5592r_setup_channel(struct iio_dev *iio_dev, | ||
502 | struct iio_chan_spec *chan, bool output, unsigned id) | ||
503 | { | ||
504 | chan->type = IIO_VOLTAGE; | ||
505 | chan->indexed = 1; | ||
506 | chan->output = output; | ||
507 | chan->channel = id; | ||
508 | chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); | ||
509 | chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); | ||
510 | chan->scan_type.sign = 'u'; | ||
511 | chan->scan_type.realbits = 12; | ||
512 | chan->scan_type.storagebits = 16; | ||
513 | chan->ext_info = ad5592r_ext_info; | ||
514 | } | ||
515 | |||
516 | static int ad5592r_alloc_channels(struct ad5592r_state *st) | ||
517 | { | ||
518 | unsigned i, curr_channel = 0, | ||
519 | num_channels = st->num_channels; | ||
520 | struct iio_dev *iio_dev = iio_priv_to_dev(st); | ||
521 | struct iio_chan_spec *channels; | ||
522 | struct fwnode_handle *child; | ||
523 | u32 reg, tmp; | ||
524 | int ret; | ||
525 | |||
526 | device_for_each_child_node(st->dev, child) { | ||
527 | ret = fwnode_property_read_u32(child, "reg", ®); | ||
528 | if (ret || reg > ARRAY_SIZE(st->channel_modes)) | ||
529 | continue; | ||
530 | |||
531 | ret = fwnode_property_read_u32(child, "adi,mode", &tmp); | ||
532 | if (!ret) | ||
533 | st->channel_modes[reg] = tmp; | ||
534 | |||
535 | fwnode_property_read_u32(child, "adi,off-state", &tmp); | ||
536 | if (!ret) | ||
537 | st->channel_offstate[reg] = tmp; | ||
538 | } | ||
539 | |||
540 | channels = devm_kzalloc(st->dev, | ||
541 | (1 + 2 * num_channels) * sizeof(*channels), GFP_KERNEL); | ||
542 | if (!channels) | ||
543 | return -ENOMEM; | ||
544 | |||
545 | for (i = 0; i < num_channels; i++) { | ||
546 | switch (st->channel_modes[i]) { | ||
547 | case CH_MODE_DAC: | ||
548 | ad5592r_setup_channel(iio_dev, &channels[curr_channel], | ||
549 | true, i); | ||
550 | curr_channel++; | ||
551 | break; | ||
552 | |||
553 | case CH_MODE_ADC: | ||
554 | ad5592r_setup_channel(iio_dev, &channels[curr_channel], | ||
555 | false, i); | ||
556 | curr_channel++; | ||
557 | break; | ||
558 | |||
559 | case CH_MODE_DAC_AND_ADC: | ||
560 | ad5592r_setup_channel(iio_dev, &channels[curr_channel], | ||
561 | true, i); | ||
562 | curr_channel++; | ||
563 | ad5592r_setup_channel(iio_dev, &channels[curr_channel], | ||
564 | false, i); | ||
565 | curr_channel++; | ||
566 | break; | ||
567 | |||
568 | default: | ||
569 | continue; | ||
570 | } | ||
571 | } | ||
572 | |||
573 | channels[curr_channel].type = IIO_TEMP; | ||
574 | channels[curr_channel].channel = 8; | ||
575 | channels[curr_channel].info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | ||
576 | BIT(IIO_CHAN_INFO_SCALE) | | ||
577 | BIT(IIO_CHAN_INFO_OFFSET); | ||
578 | curr_channel++; | ||
579 | |||
580 | iio_dev->num_channels = curr_channel; | ||
581 | iio_dev->channels = channels; | ||
582 | |||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static void ad5592r_init_scales(struct ad5592r_state *st, int vref_mV) | ||
587 | { | ||
588 | s64 tmp = (s64)vref_mV * 1000000000LL >> 12; | ||
589 | |||
590 | st->scale_avail[0][0] = | ||
591 | div_s64_rem(tmp, 1000000000LL, &st->scale_avail[0][1]); | ||
592 | st->scale_avail[1][0] = | ||
593 | div_s64_rem(tmp * 2, 1000000000LL, &st->scale_avail[1][1]); | ||
594 | } | ||
595 | |||
596 | int ad5592r_probe(struct device *dev, const char *name, | ||
597 | const struct ad5592r_rw_ops *ops) | ||
598 | { | ||
599 | struct iio_dev *iio_dev; | ||
600 | struct ad5592r_state *st; | ||
601 | int ret; | ||
602 | |||
603 | iio_dev = devm_iio_device_alloc(dev, sizeof(*st)); | ||
604 | if (!iio_dev) | ||
605 | return -ENOMEM; | ||
606 | |||
607 | st = iio_priv(iio_dev); | ||
608 | st->dev = dev; | ||
609 | st->ops = ops; | ||
610 | st->num_channels = 8; | ||
611 | dev_set_drvdata(dev, iio_dev); | ||
612 | |||
613 | st->reg = devm_regulator_get_optional(dev, "vref"); | ||
614 | if (IS_ERR(st->reg)) { | ||
615 | if ((PTR_ERR(st->reg) != -ENODEV) && dev->of_node) | ||
616 | return PTR_ERR(st->reg); | ||
617 | |||
618 | st->reg = NULL; | ||
619 | } else { | ||
620 | ret = regulator_enable(st->reg); | ||
621 | if (ret) | ||
622 | return ret; | ||
623 | } | ||
624 | |||
625 | iio_dev->dev.parent = dev; | ||
626 | iio_dev->name = name; | ||
627 | iio_dev->info = &ad5592r_info; | ||
628 | iio_dev->modes = INDIO_DIRECT_MODE; | ||
629 | |||
630 | ad5592r_init_scales(st, ad5592r_get_vref(st)); | ||
631 | |||
632 | ret = ad5592r_reset(st); | ||
633 | if (ret) | ||
634 | goto error_disable_reg; | ||
635 | |||
636 | ret = ops->reg_write(st, AD5592R_REG_PD, | ||
637 | (st->reg == NULL) ? AD5592R_REG_PD_EN_REF : 0); | ||
638 | if (ret) | ||
639 | goto error_disable_reg; | ||
640 | |||
641 | ret = ad5592r_alloc_channels(st); | ||
642 | if (ret) | ||
643 | goto error_disable_reg; | ||
644 | |||
645 | ret = ad5592r_set_channel_modes(st); | ||
646 | if (ret) | ||
647 | goto error_reset_ch_modes; | ||
648 | |||
649 | ret = iio_device_register(iio_dev); | ||
650 | if (ret) | ||
651 | goto error_reset_ch_modes; | ||
652 | |||
653 | ret = ad5592r_gpio_init(st); | ||
654 | if (ret) | ||
655 | goto error_dev_unregister; | ||
656 | |||
657 | return 0; | ||
658 | |||
659 | error_dev_unregister: | ||
660 | iio_device_unregister(iio_dev); | ||
661 | |||
662 | error_reset_ch_modes: | ||
663 | ad5592r_reset_channel_modes(st); | ||
664 | |||
665 | error_disable_reg: | ||
666 | if (st->reg) | ||
667 | regulator_disable(st->reg); | ||
668 | |||
669 | return ret; | ||
670 | } | ||
671 | EXPORT_SYMBOL_GPL(ad5592r_probe); | ||
672 | |||
673 | int ad5592r_remove(struct device *dev) | ||
674 | { | ||
675 | struct iio_dev *iio_dev = dev_get_drvdata(dev); | ||
676 | struct ad5592r_state *st = iio_priv(iio_dev); | ||
677 | |||
678 | iio_device_unregister(iio_dev); | ||
679 | ad5592r_reset_channel_modes(st); | ||
680 | ad5592r_gpio_cleanup(st); | ||
681 | |||
682 | if (st->reg) | ||
683 | regulator_disable(st->reg); | ||
684 | |||
685 | return 0; | ||
686 | } | ||
687 | EXPORT_SYMBOL_GPL(ad5592r_remove); | ||
688 | |||
689 | MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>"); | ||
690 | MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters"); | ||
691 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/iio/dac/ad5592r-base.h b/drivers/iio/dac/ad5592r-base.h new file mode 100644 index 000000000000..841457e93f85 --- /dev/null +++ b/drivers/iio/dac/ad5592r-base.h | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * AD5592R / AD5593R Digital <-> Analog converters driver | ||
3 | * | ||
4 | * Copyright 2015-2016 Analog Devices Inc. | ||
5 | * Author: Paul Cercueil <paul.cercueil@analog.com> | ||
6 | * | ||
7 | * Licensed under the GPL-2. | ||
8 | */ | ||
9 | |||
10 | #ifndef __DRIVERS_IIO_DAC_AD5592R_BASE_H__ | ||
11 | #define __DRIVERS_IIO_DAC_AD5592R_BASE_H__ | ||
12 | |||
13 | #include <linux/types.h> | ||
14 | #include <linux/cache.h> | ||
15 | #include <linux/mutex.h> | ||
16 | #include <linux/gpio/driver.h> | ||
17 | |||
18 | struct device; | ||
19 | struct ad5592r_state; | ||
20 | |||
21 | enum ad5592r_registers { | ||
22 | AD5592R_REG_NOOP = 0x0, | ||
23 | AD5592R_REG_DAC_READBACK = 0x1, | ||
24 | AD5592R_REG_ADC_SEQ = 0x2, | ||
25 | AD5592R_REG_CTRL = 0x3, | ||
26 | AD5592R_REG_ADC_EN = 0x4, | ||
27 | AD5592R_REG_DAC_EN = 0x5, | ||
28 | AD5592R_REG_PULLDOWN = 0x6, | ||
29 | AD5592R_REG_LDAC = 0x7, | ||
30 | AD5592R_REG_GPIO_OUT_EN = 0x8, | ||
31 | AD5592R_REG_GPIO_SET = 0x9, | ||
32 | AD5592R_REG_GPIO_IN_EN = 0xA, | ||
33 | AD5592R_REG_PD = 0xB, | ||
34 | AD5592R_REG_OPEN_DRAIN = 0xC, | ||
35 | AD5592R_REG_TRISTATE = 0xD, | ||
36 | AD5592R_REG_RESET = 0xF, | ||
37 | }; | ||
38 | |||
39 | #define AD5592R_REG_PD_EN_REF BIT(9) | ||
40 | #define AD5592R_REG_CTRL_ADC_RANGE BIT(5) | ||
41 | #define AD5592R_REG_CTRL_DAC_RANGE BIT(4) | ||
42 | |||
43 | struct ad5592r_rw_ops { | ||
44 | int (*write_dac)(struct ad5592r_state *st, unsigned chan, u16 value); | ||
45 | int (*read_adc)(struct ad5592r_state *st, unsigned chan, u16 *value); | ||
46 | int (*reg_write)(struct ad5592r_state *st, u8 reg, u16 value); | ||
47 | int (*reg_read)(struct ad5592r_state *st, u8 reg, u16 *value); | ||
48 | int (*gpio_read)(struct ad5592r_state *st, u8 *value); | ||
49 | }; | ||
50 | |||
51 | struct ad5592r_state { | ||
52 | struct device *dev; | ||
53 | struct regulator *reg; | ||
54 | struct gpio_chip gpiochip; | ||
55 | struct mutex gpio_lock; /* Protect cached gpio_out, gpio_val, etc. */ | ||
56 | unsigned int num_channels; | ||
57 | const struct ad5592r_rw_ops *ops; | ||
58 | int scale_avail[2][2]; | ||
59 | u16 cached_dac[8]; | ||
60 | u16 cached_gp_ctrl; | ||
61 | u8 channel_modes[8]; | ||
62 | u8 channel_offstate[8]; | ||
63 | u8 gpio_map; | ||
64 | u8 gpio_out; | ||
65 | u8 gpio_in; | ||
66 | u8 gpio_val; | ||
67 | |||
68 | __be16 spi_msg ____cacheline_aligned; | ||
69 | __be16 spi_msg_nop; | ||
70 | }; | ||
71 | |||
72 | int ad5592r_probe(struct device *dev, const char *name, | ||
73 | const struct ad5592r_rw_ops *ops); | ||
74 | int ad5592r_remove(struct device *dev); | ||
75 | |||
76 | #endif /* __DRIVERS_IIO_DAC_AD5592R_BASE_H__ */ | ||
diff --git a/drivers/iio/dac/ad5592r.c b/drivers/iio/dac/ad5592r.c new file mode 100644 index 000000000000..0b235a2c7359 --- /dev/null +++ b/drivers/iio/dac/ad5592r.c | |||
@@ -0,0 +1,164 @@ | |||
1 | /* | ||
2 | * AD5592R Digital <-> Analog converters driver | ||
3 | * | ||
4 | * Copyright 2015-2016 Analog Devices Inc. | ||
5 | * Author: Paul Cercueil <paul.cercueil@analog.com> | ||
6 | * | ||
7 | * Licensed under the GPL-2. | ||
8 | */ | ||
9 | |||
10 | #include "ad5592r-base.h" | ||
11 | |||
12 | #include <linux/bitops.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/spi/spi.h> | ||
16 | |||
17 | #define AD5592R_GPIO_READBACK_EN BIT(10) | ||
18 | #define AD5592R_LDAC_READBACK_EN BIT(6) | ||
19 | |||
20 | static int ad5592r_spi_wnop_r16(struct ad5592r_state *st, u16 *buf) | ||
21 | { | ||
22 | struct spi_device *spi = container_of(st->dev, struct spi_device, dev); | ||
23 | struct spi_transfer t = { | ||
24 | .tx_buf = &st->spi_msg_nop, | ||
25 | .rx_buf = buf, | ||
26 | .len = 2 | ||
27 | }; | ||
28 | |||
29 | st->spi_msg_nop = 0; /* NOP */ | ||
30 | |||
31 | return spi_sync_transfer(spi, &t, 1); | ||
32 | } | ||
33 | |||
34 | static int ad5592r_write_dac(struct ad5592r_state *st, unsigned chan, u16 value) | ||
35 | { | ||
36 | struct spi_device *spi = container_of(st->dev, struct spi_device, dev); | ||
37 | |||
38 | st->spi_msg = cpu_to_be16(BIT(15) | (chan << 12) | value); | ||
39 | |||
40 | return spi_write(spi, &st->spi_msg, sizeof(st->spi_msg)); | ||
41 | } | ||
42 | |||
43 | static int ad5592r_read_adc(struct ad5592r_state *st, unsigned chan, u16 *value) | ||
44 | { | ||
45 | struct spi_device *spi = container_of(st->dev, struct spi_device, dev); | ||
46 | int ret; | ||
47 | |||
48 | st->spi_msg = cpu_to_be16((AD5592R_REG_ADC_SEQ << 11) | BIT(chan)); | ||
49 | |||
50 | ret = spi_write(spi, &st->spi_msg, sizeof(st->spi_msg)); | ||
51 | if (ret) | ||
52 | return ret; | ||
53 | |||
54 | /* | ||
55 | * Invalid data: | ||
56 | * See Figure 40. Single-Channel ADC Conversion Sequence | ||
57 | */ | ||
58 | ret = ad5592r_spi_wnop_r16(st, &st->spi_msg); | ||
59 | if (ret) | ||
60 | return ret; | ||
61 | |||
62 | ret = ad5592r_spi_wnop_r16(st, &st->spi_msg); | ||
63 | if (ret) | ||
64 | return ret; | ||
65 | |||
66 | *value = be16_to_cpu(st->spi_msg); | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static int ad5592r_reg_write(struct ad5592r_state *st, u8 reg, u16 value) | ||
72 | { | ||
73 | struct spi_device *spi = container_of(st->dev, struct spi_device, dev); | ||
74 | |||
75 | st->spi_msg = cpu_to_be16((reg << 11) | value); | ||
76 | |||
77 | return spi_write(spi, &st->spi_msg, sizeof(st->spi_msg)); | ||
78 | } | ||
79 | |||
80 | static int ad5592r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value) | ||
81 | { | ||
82 | struct spi_device *spi = container_of(st->dev, struct spi_device, dev); | ||
83 | int ret; | ||
84 | |||
85 | st->spi_msg = cpu_to_be16((AD5592R_REG_LDAC << 11) | | ||
86 | AD5592R_LDAC_READBACK_EN | (reg << 2)); | ||
87 | |||
88 | ret = spi_write(spi, &st->spi_msg, sizeof(st->spi_msg)); | ||
89 | if (ret) | ||
90 | return ret; | ||
91 | |||
92 | ret = ad5592r_spi_wnop_r16(st, &st->spi_msg); | ||
93 | if (ret) | ||
94 | return ret; | ||
95 | |||
96 | *value = be16_to_cpu(st->spi_msg); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value) | ||
102 | { | ||
103 | int ret; | ||
104 | |||
105 | ret = ad5592r_reg_write(st, AD5592R_REG_GPIO_IN_EN, | ||
106 | AD5592R_GPIO_READBACK_EN | st->gpio_in); | ||
107 | if (ret) | ||
108 | return ret; | ||
109 | |||
110 | ret = ad5592r_spi_wnop_r16(st, &st->spi_msg); | ||
111 | if (ret) | ||
112 | return ret; | ||
113 | |||
114 | *value = (u8) be16_to_cpu(st->spi_msg); | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static const struct ad5592r_rw_ops ad5592r_rw_ops = { | ||
120 | .write_dac = ad5592r_write_dac, | ||
121 | .read_adc = ad5592r_read_adc, | ||
122 | .reg_write = ad5592r_reg_write, | ||
123 | .reg_read = ad5592r_reg_read, | ||
124 | .gpio_read = ad5593r_gpio_read, | ||
125 | }; | ||
126 | |||
127 | static int ad5592r_spi_probe(struct spi_device *spi) | ||
128 | { | ||
129 | const struct spi_device_id *id = spi_get_device_id(spi); | ||
130 | |||
131 | return ad5592r_probe(&spi->dev, id->name, &ad5592r_rw_ops); | ||
132 | } | ||
133 | |||
134 | static int ad5592r_spi_remove(struct spi_device *spi) | ||
135 | { | ||
136 | return ad5592r_remove(&spi->dev); | ||
137 | } | ||
138 | |||
139 | static const struct spi_device_id ad5592r_spi_ids[] = { | ||
140 | { .name = "ad5592r", }, | ||
141 | {} | ||
142 | }; | ||
143 | MODULE_DEVICE_TABLE(spi, ad5592r_spi_ids); | ||
144 | |||
145 | static const struct of_device_id ad5592r_of_match[] = { | ||
146 | { .compatible = "adi,ad5592r", }, | ||
147 | {}, | ||
148 | }; | ||
149 | MODULE_DEVICE_TABLE(of, ad5592r_of_match); | ||
150 | |||
151 | static struct spi_driver ad5592r_spi_driver = { | ||
152 | .driver = { | ||
153 | .name = "ad5592r", | ||
154 | .of_match_table = of_match_ptr(ad5592r_of_match), | ||
155 | }, | ||
156 | .probe = ad5592r_spi_probe, | ||
157 | .remove = ad5592r_spi_remove, | ||
158 | .id_table = ad5592r_spi_ids, | ||
159 | }; | ||
160 | module_spi_driver(ad5592r_spi_driver); | ||
161 | |||
162 | MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>"); | ||
163 | MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters"); | ||
164 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/iio/dac/ad5593r.c b/drivers/iio/dac/ad5593r.c new file mode 100644 index 000000000000..dca158a88f47 --- /dev/null +++ b/drivers/iio/dac/ad5593r.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * AD5593R Digital <-> Analog converters driver | ||
3 | * | ||
4 | * Copyright 2015-2016 Analog Devices Inc. | ||
5 | * Author: Paul Cercueil <paul.cercueil@analog.com> | ||
6 | * | ||
7 | * Licensed under the GPL-2. | ||
8 | */ | ||
9 | |||
10 | #include "ad5592r-base.h" | ||
11 | |||
12 | #include <linux/bitops.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/of.h> | ||
16 | |||
17 | #define AD5593R_MODE_CONF (0 << 4) | ||
18 | #define AD5593R_MODE_DAC_WRITE (1 << 4) | ||
19 | #define AD5593R_MODE_ADC_READBACK (4 << 4) | ||
20 | #define AD5593R_MODE_DAC_READBACK (5 << 4) | ||
21 | #define AD5593R_MODE_GPIO_READBACK (6 << 4) | ||
22 | #define AD5593R_MODE_REG_READBACK (7 << 4) | ||
23 | |||
24 | static int ad5593r_write_dac(struct ad5592r_state *st, unsigned chan, u16 value) | ||
25 | { | ||
26 | struct i2c_client *i2c = to_i2c_client(st->dev); | ||
27 | |||
28 | return i2c_smbus_write_word_swapped(i2c, | ||
29 | AD5593R_MODE_DAC_WRITE | chan, value); | ||
30 | } | ||
31 | |||
32 | static int ad5593r_read_adc(struct ad5592r_state *st, unsigned chan, u16 *value) | ||
33 | { | ||
34 | struct i2c_client *i2c = to_i2c_client(st->dev); | ||
35 | s32 val; | ||
36 | |||
37 | val = i2c_smbus_write_word_swapped(i2c, | ||
38 | AD5593R_MODE_CONF | AD5592R_REG_ADC_SEQ, BIT(chan)); | ||
39 | if (val < 0) | ||
40 | return (int) val; | ||
41 | |||
42 | val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_ADC_READBACK); | ||
43 | if (val < 0) | ||
44 | return (int) val; | ||
45 | |||
46 | *value = (u16) val; | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static int ad5593r_reg_write(struct ad5592r_state *st, u8 reg, u16 value) | ||
52 | { | ||
53 | struct i2c_client *i2c = to_i2c_client(st->dev); | ||
54 | |||
55 | return i2c_smbus_write_word_swapped(i2c, | ||
56 | AD5593R_MODE_CONF | reg, value); | ||
57 | } | ||
58 | |||
59 | static int ad5593r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value) | ||
60 | { | ||
61 | struct i2c_client *i2c = to_i2c_client(st->dev); | ||
62 | s32 val; | ||
63 | |||
64 | val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_REG_READBACK | reg); | ||
65 | if (val < 0) | ||
66 | return (int) val; | ||
67 | |||
68 | *value = (u16) val; | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value) | ||
74 | { | ||
75 | struct i2c_client *i2c = to_i2c_client(st->dev); | ||
76 | s32 val; | ||
77 | |||
78 | val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_GPIO_READBACK); | ||
79 | if (val < 0) | ||
80 | return (int) val; | ||
81 | |||
82 | *value = (u8) val; | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static const struct ad5592r_rw_ops ad5593r_rw_ops = { | ||
88 | .write_dac = ad5593r_write_dac, | ||
89 | .read_adc = ad5593r_read_adc, | ||
90 | .reg_write = ad5593r_reg_write, | ||
91 | .reg_read = ad5593r_reg_read, | ||
92 | .gpio_read = ad5593r_gpio_read, | ||
93 | }; | ||
94 | |||
95 | static int ad5593r_i2c_probe(struct i2c_client *i2c, | ||
96 | const struct i2c_device_id *id) | ||
97 | { | ||
98 | return ad5592r_probe(&i2c->dev, id->name, &ad5593r_rw_ops); | ||
99 | } | ||
100 | |||
101 | static int ad5593r_i2c_remove(struct i2c_client *i2c) | ||
102 | { | ||
103 | return ad5592r_remove(&i2c->dev); | ||
104 | } | ||
105 | |||
106 | static const struct i2c_device_id ad5593r_i2c_ids[] = { | ||
107 | { .name = "ad5593r", }, | ||
108 | {}, | ||
109 | }; | ||
110 | MODULE_DEVICE_TABLE(i2c, ad5593r_i2c_ids); | ||
111 | |||
112 | static const struct of_device_id ad5593r_of_match[] = { | ||
113 | { .compatible = "adi,ad5593r", }, | ||
114 | {}, | ||
115 | }; | ||
116 | MODULE_DEVICE_TABLE(of, ad5593r_of_match); | ||
117 | |||
118 | static struct i2c_driver ad5593r_driver = { | ||
119 | .driver = { | ||
120 | .name = "ad5593r", | ||
121 | .of_match_table = of_match_ptr(ad5593r_of_match), | ||
122 | }, | ||
123 | .probe = ad5593r_i2c_probe, | ||
124 | .remove = ad5593r_i2c_remove, | ||
125 | .id_table = ad5593r_i2c_ids, | ||
126 | }; | ||
127 | module_i2c_driver(ad5593r_driver); | ||
128 | |||
129 | MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>"); | ||
130 | MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters"); | ||
131 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/include/dt-bindings/iio/adi,ad5592r.h b/include/dt-bindings/iio/adi,ad5592r.h new file mode 100644 index 000000000000..c48aca1dcade --- /dev/null +++ b/include/dt-bindings/iio/adi,ad5592r.h | |||
@@ -0,0 +1,16 @@ | |||
1 | |||
2 | #ifndef _DT_BINDINGS_ADI_AD5592R_H | ||
3 | #define _DT_BINDINGS_ADI_AD5592R_H | ||
4 | |||
5 | #define CH_MODE_UNUSED 0 | ||
6 | #define CH_MODE_ADC 1 | ||
7 | #define CH_MODE_DAC 2 | ||
8 | #define CH_MODE_DAC_AND_ADC 3 | ||
9 | #define CH_MODE_GPIO 8 | ||
10 | |||
11 | #define CH_OFFSTATE_PULLDOWN 0 | ||
12 | #define CH_OFFSTATE_OUT_LOW 1 | ||
13 | #define CH_OFFSTATE_OUT_HIGH 2 | ||
14 | #define CH_OFFSTATE_OUT_TRISTATE 3 | ||
15 | |||
16 | #endif /* _DT_BINDINGS_ADI_AD5592R_H */ | ||