aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio/dac
diff options
context:
space:
mode:
authorPhilippe Reynes <tremyfr@yahoo.fr>2014-07-25 17:43:00 -0400
committerJonathan Cameron <jic23@kernel.org>2014-07-27 09:21:35 -0400
commit472988972737cdc2ee83c05931822792a2bf2f76 (patch)
treea1f9d929f6abf7a09381b2fc1f65b12398aec529 /drivers/iio/dac
parent03d795589d4e5adf83af0623ac5bac93ae2ce2a9 (diff)
iio: add support of the max5821
Signed-off-by: Philippe Reynes <tremyfr@yahoo.fr> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio/dac')
-rw-r--r--drivers/iio/dac/Kconfig8
-rw-r--r--drivers/iio/dac/Makefile1
-rw-r--r--drivers/iio/dac/max5821.c405
3 files changed, 414 insertions, 0 deletions
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index f278eff42a4c..2236ea22f98a 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -152,6 +152,14 @@ config MAX517
152 This driver can also be built as a module. If so, the module 152 This driver can also be built as a module. If so, the module
153 will be called max517. 153 will be called max517.
154 154
155config MAX5821
156 tristate "Maxim MAX5821 DAC driver"
157 depends on I2C
158 depends on OF
159 help
160 Say yes here to build support for Maxim MAX5821
161 10 bits DAC.
162
155config MCP4725 163config MCP4725
156 tristate "MCP4725 DAC driver" 164 tristate "MCP4725 DAC driver"
157 depends on I2C 165 depends on I2C
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 10107640bb46..52be7e1acf16 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -17,5 +17,6 @@ obj-$(CONFIG_AD5791) += ad5791.o
17obj-$(CONFIG_AD5686) += ad5686.o 17obj-$(CONFIG_AD5686) += ad5686.o
18obj-$(CONFIG_AD7303) += ad7303.o 18obj-$(CONFIG_AD7303) += ad7303.o
19obj-$(CONFIG_MAX517) += max517.o 19obj-$(CONFIG_MAX517) += max517.o
20obj-$(CONFIG_MAX5821) += max5821.o
20obj-$(CONFIG_MCP4725) += mcp4725.o 21obj-$(CONFIG_MCP4725) += mcp4725.o
21obj-$(CONFIG_MCP4922) += mcp4922.o 22obj-$(CONFIG_MCP4922) += mcp4922.o
diff --git a/drivers/iio/dac/max5821.c b/drivers/iio/dac/max5821.c
new file mode 100644
index 000000000000..6e914495b346
--- /dev/null
+++ b/drivers/iio/dac/max5821.c
@@ -0,0 +1,405 @@
1 /*
2 * iio/dac/max5821.c
3 * Copyright (C) 2014 Philippe Reynes
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/i2c.h>
13#include <linux/iio/iio.h>
14#include <linux/regulator/consumer.h>
15
16#define MAX5821_MAX_DAC_CHANNELS 2
17
18/* command bytes */
19#define MAX5821_LOAD_DAC_A_IN_REG_B 0x00
20#define MAX5821_LOAD_DAC_B_IN_REG_A 0x10
21#define MAX5821_EXTENDED_COMMAND_MODE 0xf0
22#define MAX5821_READ_DAC_A_COMMAND 0xf1
23#define MAX5821_READ_DAC_B_COMMAND 0xf2
24
25#define MAX5821_EXTENDED_POWER_UP 0x00
26#define MAX5821_EXTENDED_POWER_DOWN_MODE0 0x01
27#define MAX5821_EXTENDED_POWER_DOWN_MODE1 0x02
28#define MAX5821_EXTENDED_POWER_DOWN_MODE2 0x03
29#define MAX5821_EXTENDED_DAC_A 0x04
30#define MAX5821_EXTENDED_DAC_B 0x08
31
32enum max5821_device_ids {
33 ID_MAX5821,
34};
35
36struct max5821_data {
37 struct i2c_client *client;
38 struct regulator *vref_reg;
39 unsigned short vref_mv;
40 bool powerdown[MAX5821_MAX_DAC_CHANNELS];
41 u8 powerdown_mode[MAX5821_MAX_DAC_CHANNELS];
42 struct mutex lock;
43};
44
45static const char * const max5821_powerdown_modes[] = {
46 "three_state",
47 "1kohm_to_gnd",
48 "100kohm_to_gnd",
49};
50
51enum {
52 MAX5821_THREE_STATE,
53 MAX5821_1KOHM_TO_GND,
54 MAX5821_100KOHM_TO_GND
55};
56
57static int max5821_get_powerdown_mode(struct iio_dev *indio_dev,
58 const struct iio_chan_spec *chan)
59{
60 struct max5821_data *st = iio_priv(indio_dev);
61
62 return st->powerdown_mode[chan->channel];
63}
64
65static int max5821_set_powerdown_mode(struct iio_dev *indio_dev,
66 const struct iio_chan_spec *chan,
67 unsigned int mode)
68{
69 struct max5821_data *st = iio_priv(indio_dev);
70
71 st->powerdown_mode[chan->channel] = mode;
72
73 return 0;
74}
75
76static const struct iio_enum max5821_powerdown_mode_enum = {
77 .items = max5821_powerdown_modes,
78 .num_items = ARRAY_SIZE(max5821_powerdown_modes),
79 .get = max5821_get_powerdown_mode,
80 .set = max5821_set_powerdown_mode,
81};
82
83static ssize_t max5821_read_dac_powerdown(struct iio_dev *indio_dev,
84 uintptr_t private,
85 const struct iio_chan_spec *chan,
86 char *buf)
87{
88 struct max5821_data *st = iio_priv(indio_dev);
89
90 return sprintf(buf, "%d\n", st->powerdown[chan->channel]);
91}
92
93static int max5821_sync_powerdown_mode(struct max5821_data *data,
94 const struct iio_chan_spec *chan)
95{
96 u8 outbuf[2];
97
98 outbuf[0] = MAX5821_EXTENDED_COMMAND_MODE;
99
100 if (chan->channel == 0)
101 outbuf[1] = MAX5821_EXTENDED_DAC_A;
102 else
103 outbuf[1] = MAX5821_EXTENDED_DAC_B;
104
105 if (data->powerdown[chan->channel])
106 outbuf[1] |= data->powerdown_mode[chan->channel] + 1;
107 else
108 outbuf[1] |= MAX5821_EXTENDED_POWER_UP;
109
110 return i2c_master_send(data->client, outbuf, 2);
111}
112
113static ssize_t max5821_write_dac_powerdown(struct iio_dev *indio_dev,
114 uintptr_t private,
115 const struct iio_chan_spec *chan,
116 const char *buf, size_t len)
117{
118 struct max5821_data *data = iio_priv(indio_dev);
119 bool powerdown;
120 int ret;
121
122 ret = strtobool(buf, &powerdown);
123 if (ret)
124 return ret;
125
126 data->powerdown[chan->channel] = powerdown;
127
128 ret = max5821_sync_powerdown_mode(data, chan);
129 if (ret < 0)
130 return ret;
131
132 return len;
133}
134
135static const struct iio_chan_spec_ext_info max5821_ext_info[] = {
136 {
137 .name = "powerdown",
138 .read = max5821_read_dac_powerdown,
139 .write = max5821_write_dac_powerdown,
140 .shared = IIO_SEPARATE,
141 },
142 IIO_ENUM("powerdown_mode", IIO_SEPARATE, &max5821_powerdown_mode_enum),
143 IIO_ENUM_AVAILABLE("powerdown_mode", &max5821_powerdown_mode_enum),
144 { },
145};
146
147#define MAX5821_CHANNEL(chan) { \
148 .type = IIO_VOLTAGE, \
149 .indexed = 1, \
150 .output = 1, \
151 .channel = (chan), \
152 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
153 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE), \
154 .ext_info = max5821_ext_info, \
155}
156
157static const struct iio_chan_spec max5821_channels[] = {
158 MAX5821_CHANNEL(0),
159 MAX5821_CHANNEL(1)
160};
161
162static const u8 max5821_read_dac_command[] = {
163 MAX5821_READ_DAC_A_COMMAND,
164 MAX5821_READ_DAC_B_COMMAND
165};
166
167static const u8 max5821_load_dac_command[] = {
168 MAX5821_LOAD_DAC_A_IN_REG_B,
169 MAX5821_LOAD_DAC_B_IN_REG_A
170};
171
172static int max5821_get_value(struct iio_dev *indio_dev,
173 int *val, int channel)
174{
175 struct max5821_data *data = iio_priv(indio_dev);
176 struct i2c_client *client = data->client;
177 u8 outbuf[1];
178 u8 inbuf[2];
179 int ret;
180
181 if ((channel != 0) && (channel != 1))
182 return -EINVAL;
183
184 outbuf[0] = max5821_read_dac_command[channel];
185
186 mutex_lock(&data->lock);
187
188 ret = i2c_master_send(client, outbuf, 1);
189 if (ret < 0) {
190 mutex_unlock(&data->lock);
191 return ret;
192 } else if (ret != 1) {
193 mutex_unlock(&data->lock);
194 return -EIO;
195 }
196
197 ret = i2c_master_recv(client, inbuf, 2);
198 if (ret < 0) {
199 mutex_unlock(&data->lock);
200 return ret;
201 } else if (ret != 2) {
202 mutex_unlock(&data->lock);
203 return -EIO;
204 }
205
206 mutex_unlock(&data->lock);
207
208 *val = ((inbuf[0] & 0x0f) << 6) | (inbuf[1] >> 2);
209
210 return IIO_VAL_INT;
211}
212
213static int max5821_set_value(struct iio_dev *indio_dev,
214 int val, int channel)
215{
216 struct max5821_data *data = iio_priv(indio_dev);
217 struct i2c_client *client = data->client;
218 u8 outbuf[2];
219 int ret;
220
221 if ((val < 0) || (val > 1023))
222 return -EINVAL;
223
224 if ((channel != 0) && (channel != 1))
225 return -EINVAL;
226
227 outbuf[0] = max5821_load_dac_command[channel];
228 outbuf[0] |= val >> 6;
229 outbuf[1] = (val & 0x3f) << 2;
230
231 ret = i2c_master_send(client, outbuf, 2);
232 if (ret < 0)
233 return ret;
234 else if (ret != 2)
235 return -EIO;
236 else
237 return 0;
238}
239
240static int max5821_read_raw(struct iio_dev *indio_dev,
241 struct iio_chan_spec const *chan,
242 int *val, int *val2, long mask)
243{
244 struct max5821_data *data = iio_priv(indio_dev);
245
246 switch (mask) {
247 case IIO_CHAN_INFO_RAW:
248 return max5821_get_value(indio_dev, val, chan->channel);
249 case IIO_CHAN_INFO_SCALE:
250 *val = data->vref_mv;
251 *val2 = 10;
252 return IIO_VAL_FRACTIONAL_LOG2;
253 default:
254 return -EINVAL;
255 }
256}
257
258static int max5821_write_raw(struct iio_dev *indio_dev,
259 struct iio_chan_spec const *chan,
260 int val, int val2, long mask)
261{
262 if (val2 != 0)
263 return -EINVAL;
264
265 switch (mask) {
266 case IIO_CHAN_INFO_RAW:
267 return max5821_set_value(indio_dev, val, chan->channel);
268 default:
269 return -EINVAL;
270 }
271}
272
273#ifdef CONFIG_PM_SLEEP
274static int max5821_suspend(struct device *dev)
275{
276 u8 outbuf[2] = { MAX5821_EXTENDED_COMMAND_MODE,
277 MAX5821_EXTENDED_DAC_A |
278 MAX5821_EXTENDED_DAC_B |
279 MAX5821_EXTENDED_POWER_DOWN_MODE2 };
280
281 return i2c_master_send(to_i2c_client(dev), outbuf, 2);
282}
283
284static int max5821_resume(struct device *dev)
285{
286 u8 outbuf[2] = { MAX5821_EXTENDED_COMMAND_MODE,
287 MAX5821_EXTENDED_DAC_A |
288 MAX5821_EXTENDED_DAC_B |
289 MAX5821_EXTENDED_POWER_UP };
290
291 return i2c_master_send(to_i2c_client(dev), outbuf, 2);
292}
293
294static SIMPLE_DEV_PM_OPS(max5821_pm_ops, max5821_suspend, max5821_resume);
295#define MAX5821_PM_OPS (&max5821_pm_ops)
296#else
297#define MAX5821_PM_OPS NULL
298#endif /* CONFIG_PM_SLEEP */
299
300static const struct iio_info max5821_info = {
301 .read_raw = max5821_read_raw,
302 .write_raw = max5821_write_raw,
303 .driver_module = THIS_MODULE,
304};
305
306static int max5821_probe(struct i2c_client *client,
307 const struct i2c_device_id *id)
308{
309 struct max5821_data *data;
310 struct iio_dev *indio_dev;
311 u32 tmp;
312 int ret;
313
314 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
315 if (!indio_dev)
316 return -ENOMEM;
317 data = iio_priv(indio_dev);
318 i2c_set_clientdata(client, indio_dev);
319 data->client = client;
320 mutex_init(&data->lock);
321
322 /* max5821 start in powerdown mode 100Kohm to ground */
323 for (tmp = 0; tmp < MAX5821_MAX_DAC_CHANNELS; tmp++) {
324 data->powerdown[tmp] = true;
325 data->powerdown_mode[tmp] = MAX5821_100KOHM_TO_GND;
326 }
327
328 data->vref_reg = devm_regulator_get(&client->dev, "vref");
329 if (IS_ERR(data->vref_reg)) {
330 ret = PTR_ERR(data->vref_reg);
331 dev_err(&client->dev,
332 "Failed to get vref regulator: %d\n", ret);
333 goto error_free_reg;
334 }
335
336 ret = regulator_enable(data->vref_reg);
337 if (ret) {
338 dev_err(&client->dev,
339 "Failed to enable vref regulator: %d\n", ret);
340 goto error_free_reg;
341 }
342
343 ret = regulator_get_voltage(data->vref_reg);
344 if (ret < 0) {
345 dev_err(&client->dev,
346 "Failed to get voltage on regulator: %d\n", ret);
347 goto error_disable_reg;
348 }
349
350 data->vref_mv = ret / 1000;
351
352 indio_dev->name = id->name;
353 indio_dev->dev.parent = &client->dev;
354 indio_dev->num_channels = ARRAY_SIZE(max5821_channels);
355 indio_dev->channels = max5821_channels;
356 indio_dev->modes = INDIO_DIRECT_MODE;
357 indio_dev->info = &max5821_info;
358
359 return iio_device_register(indio_dev);
360
361error_disable_reg:
362 regulator_disable(data->vref_reg);
363
364error_free_reg:
365
366 return ret;
367}
368
369static int max5821_remove(struct i2c_client *client)
370{
371 struct iio_dev *indio_dev = i2c_get_clientdata(client);
372 struct max5821_data *data = iio_priv(indio_dev);
373
374 iio_device_unregister(indio_dev);
375 regulator_disable(data->vref_reg);
376
377 return 0;
378}
379
380static const struct i2c_device_id max5821_id[] = {
381 { "max5821", ID_MAX5821 },
382 { }
383};
384MODULE_DEVICE_TABLE(i2c, max5821_id);
385
386static const struct of_device_id max5821_of_match[] = {
387 { .compatible = "maxim,max5821" },
388 { }
389};
390
391static struct i2c_driver max5821_driver = {
392 .driver = {
393 .name = "max5821",
394 .pm = MAX5821_PM_OPS,
395 .owner = THIS_MODULE,
396 },
397 .probe = max5821_probe,
398 .remove = max5821_remove,
399 .id_table = max5821_id,
400};
401module_i2c_driver(max5821_driver);
402
403MODULE_AUTHOR("Philippe Reynes <tremyfr@yahoo.fr>");
404MODULE_DESCRIPTION("MAX5821 DAC");
405MODULE_LICENSE("GPL v2");