Commit | Line | Data |
---|---|---|
6ddc5fb4 RS |
1 | /* |
2 | * max517.c - Support for Maxim MAX517, MAX518 and MAX519 | |
3 | * | |
4 | * Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.de> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, write to the Free Software | |
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
19 | */ | |
20 | ||
21 | #include <linux/module.h> | |
22 | #include <linux/init.h> | |
23 | #include <linux/slab.h> | |
24 | #include <linux/jiffies.h> | |
25 | #include <linux/i2c.h> | |
26 | #include <linux/err.h> | |
27 | ||
06458e27 JC |
28 | #include <linux/iio/iio.h> |
29 | #include <linux/iio/sysfs.h> | |
6ddc5fb4 RS |
30 | #include "dac.h" |
31 | ||
32 | #include "max517.h" | |
33 | ||
34 | #define MAX517_DRV_NAME "max517" | |
35 | ||
36 | /* Commands */ | |
37 | #define COMMAND_CHANNEL0 0x00 | |
38 | #define COMMAND_CHANNEL1 0x01 /* for MAX518 and MAX519 */ | |
39 | #define COMMAND_PD 0x08 /* Power Down */ | |
40 | ||
41 | enum max517_device_ids { | |
42 | ID_MAX517, | |
43 | ID_MAX518, | |
44 | ID_MAX519, | |
45 | }; | |
46 | ||
47 | struct max517_data { | |
48 | struct iio_dev *indio_dev; | |
826514b4 | 49 | struct i2c_client *client; |
6ddc5fb4 RS |
50 | unsigned short vref_mv[2]; |
51 | }; | |
52 | ||
53 | /* | |
54 | * channel: bit 0: channel 1 | |
55 | * bit 1: channel 2 | |
56 | * (this way, it's possible to set both channels at once) | |
57 | */ | |
58 | static ssize_t max517_set_value(struct device *dev, | |
59 | struct device_attribute *attr, | |
60 | const char *buf, size_t count, int channel) | |
61 | { | |
638e59fc JC |
62 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
63 | struct max517_data *data = iio_priv(indio_dev); | |
826514b4 | 64 | struct i2c_client *client = data->client; |
6ddc5fb4 RS |
65 | u8 outbuf[4]; /* 1x or 2x command + value */ |
66 | int outbuf_size = 0; | |
67 | int res; | |
68 | long val; | |
69 | ||
70 | res = strict_strtol(buf, 10, &val); | |
71 | ||
72 | if (res) | |
73 | return res; | |
74 | ||
75 | if (val < 0 || val > 255) | |
76 | return -EINVAL; | |
77 | ||
78 | if (channel & 1) { | |
79 | outbuf[outbuf_size++] = COMMAND_CHANNEL0; | |
80 | outbuf[outbuf_size++] = val; | |
81 | } | |
82 | if (channel & 2) { | |
83 | outbuf[outbuf_size++] = COMMAND_CHANNEL1; | |
84 | outbuf[outbuf_size++] = val; | |
85 | } | |
86 | ||
87 | /* | |
88 | * At this point, there are always 1 or 2 two-byte commands in | |
89 | * outbuf. With 2 commands, the device can set two outputs | |
90 | * simultaneously, latching the values upon the end of the I2C | |
91 | * transfer. | |
92 | */ | |
93 | ||
94 | res = i2c_master_send(client, outbuf, outbuf_size); | |
95 | if (res < 0) | |
96 | return res; | |
97 | ||
98 | return count; | |
99 | } | |
100 | ||
101 | static ssize_t max517_set_value_1(struct device *dev, | |
102 | struct device_attribute *attr, | |
103 | const char *buf, size_t count) | |
104 | { | |
105 | return max517_set_value(dev, attr, buf, count, 1); | |
106 | } | |
107 | static IIO_DEV_ATTR_OUT_RAW(1, max517_set_value_1, 0); | |
108 | ||
109 | static ssize_t max517_set_value_2(struct device *dev, | |
110 | struct device_attribute *attr, | |
111 | const char *buf, size_t count) | |
112 | { | |
113 | return max517_set_value(dev, attr, buf, count, 2); | |
114 | } | |
115 | static IIO_DEV_ATTR_OUT_RAW(2, max517_set_value_2, 1); | |
116 | ||
117 | static ssize_t max517_set_value_both(struct device *dev, | |
118 | struct device_attribute *attr, | |
119 | const char *buf, size_t count) | |
120 | { | |
121 | return max517_set_value(dev, attr, buf, count, 3); | |
122 | } | |
322c9563 JC |
123 | static IIO_DEVICE_ATTR_NAMED(out_voltage1and2_raw, |
124 | out_voltage1&2_raw, S_IWUSR, NULL, | |
125 | max517_set_value_both, -1); | |
6ddc5fb4 RS |
126 | |
127 | static ssize_t max517_show_scale(struct device *dev, | |
128 | struct device_attribute *attr, | |
129 | char *buf, int channel) | |
130 | { | |
638e59fc JC |
131 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
132 | struct max517_data *data = iio_priv(indio_dev); | |
6ddc5fb4 RS |
133 | /* Corresponds to Vref / 2^(bits) */ |
134 | unsigned int scale_uv = (data->vref_mv[channel - 1] * 1000) >> 8; | |
135 | ||
136 | return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); | |
137 | } | |
138 | ||
139 | static ssize_t max517_show_scale1(struct device *dev, | |
140 | struct device_attribute *attr, | |
141 | char *buf) | |
142 | { | |
143 | return max517_show_scale(dev, attr, buf, 1); | |
144 | } | |
322c9563 JC |
145 | static IIO_DEVICE_ATTR(out_voltage1_scale, S_IRUGO, |
146 | max517_show_scale1, NULL, 0); | |
6ddc5fb4 RS |
147 | |
148 | static ssize_t max517_show_scale2(struct device *dev, | |
149 | struct device_attribute *attr, | |
150 | char *buf) | |
151 | { | |
152 | return max517_show_scale(dev, attr, buf, 2); | |
153 | } | |
322c9563 JC |
154 | static IIO_DEVICE_ATTR(out_voltage2_scale, S_IRUGO, |
155 | max517_show_scale2, NULL, 0); | |
6ddc5fb4 | 156 | |
826514b4 | 157 | /* On MAX517 variant, we have one output */ |
6ddc5fb4 | 158 | static struct attribute *max517_attributes[] = { |
322c9563 JC |
159 | &iio_dev_attr_out_voltage1_raw.dev_attr.attr, |
160 | &iio_dev_attr_out_voltage1_scale.dev_attr.attr, | |
6ddc5fb4 RS |
161 | NULL |
162 | }; | |
163 | ||
164 | static struct attribute_group max517_attribute_group = { | |
165 | .attrs = max517_attributes, | |
166 | }; | |
167 | ||
826514b4 | 168 | /* On MAX518 and MAX519 variant, we have two outputs */ |
6ddc5fb4 | 169 | static struct attribute *max518_attributes[] = { |
322c9563 JC |
170 | &iio_dev_attr_out_voltage1_raw.dev_attr.attr, |
171 | &iio_dev_attr_out_voltage1_scale.dev_attr.attr, | |
172 | &iio_dev_attr_out_voltage2_raw.dev_attr.attr, | |
173 | &iio_dev_attr_out_voltage2_scale.dev_attr.attr, | |
174 | &iio_dev_attr_out_voltage1and2_raw.dev_attr.attr, | |
6ddc5fb4 RS |
175 | NULL |
176 | }; | |
177 | ||
178 | static struct attribute_group max518_attribute_group = { | |
179 | .attrs = max518_attributes, | |
180 | }; | |
181 | ||
01788c53 LPC |
182 | #ifdef CONFIG_PM_SLEEP |
183 | static int max517_suspend(struct device *dev) | |
6ddc5fb4 RS |
184 | { |
185 | u8 outbuf = COMMAND_PD; | |
186 | ||
01788c53 | 187 | return i2c_master_send(to_i2c_client(dev), &outbuf, 1); |
6ddc5fb4 RS |
188 | } |
189 | ||
01788c53 | 190 | static int max517_resume(struct device *dev) |
6ddc5fb4 RS |
191 | { |
192 | u8 outbuf = 0; | |
193 | ||
01788c53 | 194 | return i2c_master_send(to_i2c_client(dev), &outbuf, 1); |
6ddc5fb4 RS |
195 | } |
196 | ||
01788c53 LPC |
197 | static SIMPLE_DEV_PM_OPS(max517_pm_ops, max517_suspend, max517_resume); |
198 | #define MAX517_PM_OPS (&max517_pm_ops) | |
199 | #else | |
200 | #define MAX517_PM_OPS NULL | |
201 | #endif | |
202 | ||
6fe8135f JC |
203 | static const struct iio_info max517_info = { |
204 | .attrs = &max517_attribute_group, | |
205 | .driver_module = THIS_MODULE, | |
206 | }; | |
207 | ||
208 | static const struct iio_info max518_info = { | |
8aa460e9 | 209 | .attrs = &max518_attribute_group, |
6fe8135f JC |
210 | .driver_module = THIS_MODULE, |
211 | }; | |
212 | ||
6ddc5fb4 RS |
213 | static int max517_probe(struct i2c_client *client, |
214 | const struct i2c_device_id *id) | |
215 | { | |
216 | struct max517_data *data; | |
cada11fa | 217 | struct iio_dev *indio_dev; |
6ddc5fb4 RS |
218 | struct max517_platform_data *platform_data = client->dev.platform_data; |
219 | int err; | |
220 | ||
cada11fa JC |
221 | indio_dev = iio_allocate_device(sizeof(*data)); |
222 | if (indio_dev == NULL) { | |
6ddc5fb4 RS |
223 | err = -ENOMEM; |
224 | goto exit; | |
225 | } | |
cada11fa JC |
226 | data = iio_priv(indio_dev); |
227 | i2c_set_clientdata(client, indio_dev); | |
826514b4 RS |
228 | data->client = client; |
229 | ||
6ddc5fb4 | 230 | /* establish that the iio_dev is a child of the i2c device */ |
cada11fa | 231 | indio_dev->dev.parent = &client->dev; |
6ddc5fb4 RS |
232 | |
233 | /* reduced attribute set for MAX517 */ | |
234 | if (id->driver_data == ID_MAX517) | |
cada11fa | 235 | indio_dev->info = &max517_info; |
6ddc5fb4 | 236 | else |
cada11fa JC |
237 | indio_dev->info = &max518_info; |
238 | indio_dev->modes = INDIO_DIRECT_MODE; | |
6ddc5fb4 RS |
239 | |
240 | /* | |
241 | * Reference voltage on MAX518 and default is 5V, else take vref_mv | |
242 | * from platform_data | |
243 | */ | |
244 | if (id->driver_data == ID_MAX518 || !platform_data) { | |
245 | data->vref_mv[0] = data->vref_mv[1] = 5000; /* mV */ | |
246 | } else { | |
247 | data->vref_mv[0] = platform_data->vref_mv[0]; | |
248 | data->vref_mv[1] = platform_data->vref_mv[1]; | |
249 | } | |
250 | ||
cada11fa | 251 | err = iio_device_register(indio_dev); |
6ddc5fb4 RS |
252 | if (err) |
253 | goto exit_free_device; | |
254 | ||
255 | dev_info(&client->dev, "DAC registered\n"); | |
256 | ||
257 | return 0; | |
258 | ||
259 | exit_free_device: | |
cada11fa | 260 | iio_free_device(indio_dev); |
6ddc5fb4 RS |
261 | exit: |
262 | return err; | |
263 | } | |
264 | ||
265 | static int max517_remove(struct i2c_client *client) | |
266 | { | |
cada11fa | 267 | iio_free_device(i2c_get_clientdata(client)); |
6ddc5fb4 RS |
268 | |
269 | return 0; | |
270 | } | |
271 | ||
272 | static const struct i2c_device_id max517_id[] = { | |
273 | { "max517", ID_MAX517 }, | |
274 | { "max518", ID_MAX518 }, | |
275 | { "max519", ID_MAX519 }, | |
276 | { } | |
277 | }; | |
278 | MODULE_DEVICE_TABLE(i2c, max517_id); | |
279 | ||
280 | static struct i2c_driver max517_driver = { | |
281 | .driver = { | |
282 | .name = MAX517_DRV_NAME, | |
01788c53 | 283 | .pm = MAX517_PM_OPS, |
6ddc5fb4 RS |
284 | }, |
285 | .probe = max517_probe, | |
286 | .remove = max517_remove, | |
6ddc5fb4 RS |
287 | .id_table = max517_id, |
288 | }; | |
6e5af184 | 289 | module_i2c_driver(max517_driver); |
6ddc5fb4 RS |
290 | |
291 | MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>"); | |
292 | MODULE_DESCRIPTION("MAX517/MAX518/MAX519 8-bit DAC"); | |
293 | MODULE_LICENSE("GPL"); |