1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * max517.c - Support for Maxim MAX517, MAX518 and MAX519 |
4 | * |
5 | * Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.de> |
6 | */ |
7 | |
8 | #include <linux/module.h> |
9 | #include <linux/slab.h> |
10 | #include <linux/jiffies.h> |
11 | #include <linux/i2c.h> |
12 | #include <linux/err.h> |
13 | |
14 | #include <linux/iio/iio.h> |
15 | #include <linux/iio/sysfs.h> |
16 | #include <linux/iio/dac/max517.h> |
17 | |
18 | #define MAX517_DRV_NAME "max517" |
19 | |
20 | /* Commands */ |
21 | #define COMMAND_CHANNEL0 0x00 |
22 | #define COMMAND_CHANNEL1 0x01 /* for MAX518 and MAX519 */ |
23 | #define COMMAND_PD 0x08 /* Power Down */ |
24 | |
25 | enum max517_device_ids { |
26 | ID_MAX517, |
27 | ID_MAX518, |
28 | ID_MAX519, |
29 | ID_MAX520, |
30 | ID_MAX521, |
31 | }; |
32 | |
33 | struct max517_data { |
34 | struct i2c_client *client; |
35 | unsigned short vref_mv[8]; |
36 | }; |
37 | |
38 | /* |
39 | * channel: bit 0: channel 1 |
40 | * bit 1: channel 2 |
41 | * (this way, it's possible to set both channels at once) |
42 | */ |
43 | static int max517_set_value(struct iio_dev *indio_dev, |
44 | long val, int channel) |
45 | { |
46 | struct max517_data *data = iio_priv(indio_dev); |
47 | struct i2c_client *client = data->client; |
48 | u8 outbuf[2]; |
49 | int res; |
50 | |
51 | if (val < 0 || val > 255) |
52 | return -EINVAL; |
53 | |
54 | outbuf[0] = channel; |
55 | outbuf[1] = val; |
56 | |
57 | res = i2c_master_send(client, buf: outbuf, count: 2); |
58 | if (res < 0) |
59 | return res; |
60 | else if (res != 2) |
61 | return -EIO; |
62 | else |
63 | return 0; |
64 | } |
65 | |
66 | static int max517_read_raw(struct iio_dev *indio_dev, |
67 | struct iio_chan_spec const *chan, |
68 | int *val, |
69 | int *val2, |
70 | long m) |
71 | { |
72 | struct max517_data *data = iio_priv(indio_dev); |
73 | |
74 | switch (m) { |
75 | case IIO_CHAN_INFO_SCALE: |
76 | /* Corresponds to Vref / 2^(bits) */ |
77 | *val = data->vref_mv[chan->channel]; |
78 | *val2 = 8; |
79 | return IIO_VAL_FRACTIONAL_LOG2; |
80 | default: |
81 | break; |
82 | } |
83 | return -EINVAL; |
84 | } |
85 | |
86 | static int max517_write_raw(struct iio_dev *indio_dev, |
87 | struct iio_chan_spec const *chan, int val, int val2, long mask) |
88 | { |
89 | int ret; |
90 | |
91 | switch (mask) { |
92 | case IIO_CHAN_INFO_RAW: |
93 | ret = max517_set_value(indio_dev, val, channel: chan->channel); |
94 | break; |
95 | default: |
96 | ret = -EINVAL; |
97 | break; |
98 | } |
99 | |
100 | return ret; |
101 | } |
102 | |
103 | static int max517_suspend(struct device *dev) |
104 | { |
105 | u8 outbuf = COMMAND_PD; |
106 | |
107 | return i2c_master_send(to_i2c_client(dev), buf: &outbuf, count: 1); |
108 | } |
109 | |
110 | static int max517_resume(struct device *dev) |
111 | { |
112 | u8 outbuf = 0; |
113 | |
114 | return i2c_master_send(to_i2c_client(dev), buf: &outbuf, count: 1); |
115 | } |
116 | |
117 | static DEFINE_SIMPLE_DEV_PM_OPS(max517_pm_ops, max517_suspend, max517_resume); |
118 | |
119 | static const struct iio_info max517_info = { |
120 | .read_raw = max517_read_raw, |
121 | .write_raw = max517_write_raw, |
122 | }; |
123 | |
124 | #define MAX517_CHANNEL(chan) { \ |
125 | .type = IIO_VOLTAGE, \ |
126 | .indexed = 1, \ |
127 | .output = 1, \ |
128 | .channel = (chan), \ |
129 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
130 | BIT(IIO_CHAN_INFO_SCALE), \ |
131 | } |
132 | |
133 | static const struct iio_chan_spec max517_channels[] = { |
134 | MAX517_CHANNEL(0), |
135 | MAX517_CHANNEL(1), |
136 | MAX517_CHANNEL(2), |
137 | MAX517_CHANNEL(3), |
138 | MAX517_CHANNEL(4), |
139 | MAX517_CHANNEL(5), |
140 | MAX517_CHANNEL(6), |
141 | MAX517_CHANNEL(7), |
142 | }; |
143 | |
144 | static int max517_probe(struct i2c_client *client) |
145 | { |
146 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
147 | struct max517_data *data; |
148 | struct iio_dev *indio_dev; |
149 | struct max517_platform_data *platform_data = client->dev.platform_data; |
150 | int chan; |
151 | |
152 | indio_dev = devm_iio_device_alloc(parent: &client->dev, sizeof_priv: sizeof(*data)); |
153 | if (!indio_dev) |
154 | return -ENOMEM; |
155 | data = iio_priv(indio_dev); |
156 | data->client = client; |
157 | |
158 | switch (id->driver_data) { |
159 | case ID_MAX521: |
160 | indio_dev->num_channels = 8; |
161 | break; |
162 | case ID_MAX520: |
163 | indio_dev->num_channels = 4; |
164 | break; |
165 | case ID_MAX519: |
166 | case ID_MAX518: |
167 | indio_dev->num_channels = 2; |
168 | break; |
169 | default: /* single channel for MAX517 */ |
170 | indio_dev->num_channels = 1; |
171 | break; |
172 | } |
173 | indio_dev->channels = max517_channels; |
174 | indio_dev->modes = INDIO_DIRECT_MODE; |
175 | indio_dev->info = &max517_info; |
176 | |
177 | /* |
178 | * Reference voltage on MAX518 and default is 5V, else take vref_mv |
179 | * from platform_data |
180 | */ |
181 | for (chan = 0; chan < indio_dev->num_channels; chan++) { |
182 | if (id->driver_data == ID_MAX518 || !platform_data) |
183 | data->vref_mv[chan] = 5000; /* mV */ |
184 | else |
185 | data->vref_mv[chan] = platform_data->vref_mv[chan]; |
186 | } |
187 | |
188 | return devm_iio_device_register(&client->dev, indio_dev); |
189 | } |
190 | |
191 | static const struct i2c_device_id max517_id[] = { |
192 | { "max517" , ID_MAX517 }, |
193 | { "max518" , ID_MAX518 }, |
194 | { "max519" , ID_MAX519 }, |
195 | { "max520" , ID_MAX520 }, |
196 | { "max521" , ID_MAX521 }, |
197 | { } |
198 | }; |
199 | MODULE_DEVICE_TABLE(i2c, max517_id); |
200 | |
201 | static struct i2c_driver max517_driver = { |
202 | .driver = { |
203 | .name = MAX517_DRV_NAME, |
204 | .pm = pm_sleep_ptr(&max517_pm_ops), |
205 | }, |
206 | .probe = max517_probe, |
207 | .id_table = max517_id, |
208 | }; |
209 | module_i2c_driver(max517_driver); |
210 | |
211 | MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>" ); |
212 | MODULE_DESCRIPTION("MAX517/518/519/520/521 8-bit DAC" ); |
213 | MODULE_LICENSE("GPL" ); |
214 | |