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> | |
dbdc025b | 30 | #include <linux/iio/dac/max517.h> |
6ddc5fb4 RS |
31 | |
32 | #define MAX517_DRV_NAME "max517" | |
33 | ||
34 | /* Commands */ | |
35 | #define COMMAND_CHANNEL0 0x00 | |
36 | #define COMMAND_CHANNEL1 0x01 /* for MAX518 and MAX519 */ | |
37 | #define COMMAND_PD 0x08 /* Power Down */ | |
38 | ||
39 | enum max517_device_ids { | |
40 | ID_MAX517, | |
41 | ID_MAX518, | |
42 | ID_MAX519, | |
43 | }; | |
44 | ||
45 | struct max517_data { | |
826514b4 | 46 | struct i2c_client *client; |
6ddc5fb4 RS |
47 | unsigned short vref_mv[2]; |
48 | }; | |
49 | ||
50 | /* | |
51 | * channel: bit 0: channel 1 | |
52 | * bit 1: channel 2 | |
53 | * (this way, it's possible to set both channels at once) | |
54 | */ | |
4cd8d874 LPC |
55 | static int max517_set_value(struct iio_dev *indio_dev, |
56 | long val, int channel) | |
6ddc5fb4 | 57 | { |
638e59fc | 58 | struct max517_data *data = iio_priv(indio_dev); |
826514b4 | 59 | struct i2c_client *client = data->client; |
4cd8d874 | 60 | u8 outbuf[2]; |
6ddc5fb4 | 61 | int res; |
6ddc5fb4 RS |
62 | |
63 | if (val < 0 || val > 255) | |
64 | return -EINVAL; | |
65 | ||
4cd8d874 LPC |
66 | outbuf[0] = channel; |
67 | outbuf[1] = val; | |
6ddc5fb4 | 68 | |
4cd8d874 | 69 | res = i2c_master_send(client, outbuf, 2); |
6ddc5fb4 RS |
70 | if (res < 0) |
71 | return res; | |
4cd8d874 LPC |
72 | else if (res != 2) |
73 | return -EIO; | |
74 | else | |
75 | return 0; | |
6ddc5fb4 | 76 | } |
6ddc5fb4 | 77 | |
4cd8d874 LPC |
78 | static int max517_read_raw(struct iio_dev *indio_dev, |
79 | struct iio_chan_spec const *chan, | |
80 | int *val, | |
81 | int *val2, | |
82 | long m) | |
6ddc5fb4 | 83 | { |
638e59fc | 84 | struct max517_data *data = iio_priv(indio_dev); |
4cd8d874 LPC |
85 | unsigned int scale_uv; |
86 | ||
87 | switch (m) { | |
88 | case IIO_CHAN_INFO_SCALE: | |
89 | /* Corresponds to Vref / 2^(bits) */ | |
90 | scale_uv = (data->vref_mv[chan->channel] * 1000) >> 8; | |
91 | *val = scale_uv / 1000000; | |
92 | *val2 = scale_uv % 1000000; | |
93 | return IIO_VAL_INT_PLUS_MICRO; | |
94 | default: | |
95 | break; | |
96 | } | |
97 | return -EINVAL; | |
6ddc5fb4 RS |
98 | } |
99 | ||
4cd8d874 LPC |
100 | static int max517_write_raw(struct iio_dev *indio_dev, |
101 | struct iio_chan_spec const *chan, int val, int val2, long mask) | |
6ddc5fb4 | 102 | { |
4cd8d874 LPC |
103 | int ret; |
104 | ||
105 | switch (mask) { | |
106 | case IIO_CHAN_INFO_RAW: | |
107 | ret = max517_set_value(indio_dev, val, chan->channel); | |
108 | break; | |
109 | default: | |
110 | ret = -EINVAL; | |
111 | break; | |
112 | } | |
6ddc5fb4 | 113 | |
4cd8d874 | 114 | return ret; |
6ddc5fb4 | 115 | } |
6ddc5fb4 | 116 | |
01788c53 LPC |
117 | #ifdef CONFIG_PM_SLEEP |
118 | static int max517_suspend(struct device *dev) | |
6ddc5fb4 RS |
119 | { |
120 | u8 outbuf = COMMAND_PD; | |
121 | ||
01788c53 | 122 | return i2c_master_send(to_i2c_client(dev), &outbuf, 1); |
6ddc5fb4 RS |
123 | } |
124 | ||
01788c53 | 125 | static int max517_resume(struct device *dev) |
6ddc5fb4 RS |
126 | { |
127 | u8 outbuf = 0; | |
128 | ||
01788c53 | 129 | return i2c_master_send(to_i2c_client(dev), &outbuf, 1); |
6ddc5fb4 RS |
130 | } |
131 | ||
01788c53 LPC |
132 | static SIMPLE_DEV_PM_OPS(max517_pm_ops, max517_suspend, max517_resume); |
133 | #define MAX517_PM_OPS (&max517_pm_ops) | |
134 | #else | |
135 | #define MAX517_PM_OPS NULL | |
136 | #endif | |
137 | ||
6fe8135f | 138 | static const struct iio_info max517_info = { |
4cd8d874 LPC |
139 | .read_raw = max517_read_raw, |
140 | .write_raw = max517_write_raw, | |
6fe8135f JC |
141 | .driver_module = THIS_MODULE, |
142 | }; | |
143 | ||
4cd8d874 LPC |
144 | #define MAX517_CHANNEL(chan) { \ |
145 | .type = IIO_VOLTAGE, \ | |
146 | .indexed = 1, \ | |
147 | .output = 1, \ | |
148 | .channel = (chan), \ | |
040b837e JC |
149 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
150 | BIT(IIO_CHAN_INFO_SCALE), \ | |
4cd8d874 LPC |
151 | .scan_type = IIO_ST('u', 8, 8, 0), \ |
152 | } | |
153 | ||
154 | static const struct iio_chan_spec max517_channels[] = { | |
155 | MAX517_CHANNEL(0), | |
156 | MAX517_CHANNEL(1) | |
6fe8135f JC |
157 | }; |
158 | ||
fc52692c | 159 | static int max517_probe(struct i2c_client *client, |
6ddc5fb4 RS |
160 | const struct i2c_device_id *id) |
161 | { | |
162 | struct max517_data *data; | |
cada11fa | 163 | struct iio_dev *indio_dev; |
6ddc5fb4 RS |
164 | struct max517_platform_data *platform_data = client->dev.platform_data; |
165 | int err; | |
166 | ||
cc566fd5 SK |
167 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); |
168 | if (!indio_dev) | |
169 | return -ENOMEM; | |
cada11fa JC |
170 | data = iio_priv(indio_dev); |
171 | i2c_set_clientdata(client, indio_dev); | |
826514b4 RS |
172 | data->client = client; |
173 | ||
6ddc5fb4 | 174 | /* establish that the iio_dev is a child of the i2c device */ |
cada11fa | 175 | indio_dev->dev.parent = &client->dev; |
6ddc5fb4 | 176 | |
4cd8d874 | 177 | /* reduced channel set for MAX517 */ |
6ddc5fb4 | 178 | if (id->driver_data == ID_MAX517) |
4cd8d874 | 179 | indio_dev->num_channels = 1; |
6ddc5fb4 | 180 | else |
4cd8d874 LPC |
181 | indio_dev->num_channels = 2; |
182 | indio_dev->channels = max517_channels; | |
cada11fa | 183 | indio_dev->modes = INDIO_DIRECT_MODE; |
4cd8d874 | 184 | indio_dev->info = &max517_info; |
6ddc5fb4 RS |
185 | |
186 | /* | |
187 | * Reference voltage on MAX518 and default is 5V, else take vref_mv | |
188 | * from platform_data | |
189 | */ | |
190 | if (id->driver_data == ID_MAX518 || !platform_data) { | |
191 | data->vref_mv[0] = data->vref_mv[1] = 5000; /* mV */ | |
192 | } else { | |
193 | data->vref_mv[0] = platform_data->vref_mv[0]; | |
194 | data->vref_mv[1] = platform_data->vref_mv[1]; | |
195 | } | |
196 | ||
cada11fa | 197 | err = iio_device_register(indio_dev); |
6ddc5fb4 | 198 | if (err) |
cc566fd5 | 199 | return err; |
6ddc5fb4 RS |
200 | |
201 | dev_info(&client->dev, "DAC registered\n"); | |
202 | ||
203 | return 0; | |
6ddc5fb4 RS |
204 | } |
205 | ||
fc52692c | 206 | static int max517_remove(struct i2c_client *client) |
6ddc5fb4 | 207 | { |
e8ccc11f | 208 | iio_device_unregister(i2c_get_clientdata(client)); |
6ddc5fb4 RS |
209 | return 0; |
210 | } | |
211 | ||
212 | static const struct i2c_device_id max517_id[] = { | |
213 | { "max517", ID_MAX517 }, | |
214 | { "max518", ID_MAX518 }, | |
215 | { "max519", ID_MAX519 }, | |
216 | { } | |
217 | }; | |
218 | MODULE_DEVICE_TABLE(i2c, max517_id); | |
219 | ||
220 | static struct i2c_driver max517_driver = { | |
221 | .driver = { | |
222 | .name = MAX517_DRV_NAME, | |
01788c53 | 223 | .pm = MAX517_PM_OPS, |
6ddc5fb4 RS |
224 | }, |
225 | .probe = max517_probe, | |
fc52692c | 226 | .remove = max517_remove, |
6ddc5fb4 RS |
227 | .id_table = max517_id, |
228 | }; | |
6e5af184 | 229 | module_i2c_driver(max517_driver); |
6ddc5fb4 RS |
230 | |
231 | MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>"); | |
232 | MODULE_DESCRIPTION("MAX517/MAX518/MAX519 8-bit DAC"); | |
233 | MODULE_LICENSE("GPL"); |