xref: /linux/drivers/iio/dac/ds4424.c (revision 1fd1dc41724319406b0aff221a352a400b0ddfc5)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Maxim Integrated
4  * 7-bit, Multi-Channel Sink/Source Current DAC Driver
5  * Copyright (C) 2017 Maxim Integrated
6  */
7 
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/i2c.h>
11 #include <linux/regulator/consumer.h>
12 #include <linux/err.h>
13 #include <linux/delay.h>
14 #include <linux/iio/iio.h>
15 #include <linux/iio/driver.h>
16 #include <linux/iio/machine.h>
17 
18 #define DS4422_MAX_DAC_CHANNELS		2
19 #define DS4424_MAX_DAC_CHANNELS		4
20 
21 #define DS4424_DAC_ADDR(chan)   ((chan) + 0xf8)
22 #define DS4424_SOURCE_I		1
23 #define DS4424_SINK_I		0
24 
25 #define DS4424_CHANNEL(chan) { \
26 	.type = IIO_CURRENT, \
27 	.indexed = 1, \
28 	.output = 1, \
29 	.channel = chan, \
30 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
31 }
32 
33 /*
34  * DS4424 DAC control register 8 bits
35  * [7]		0: to sink; 1: to source
36  * [6:0]	steps to sink/source
37  * bit[7] looks like a sign bit, but the value of the register is
38  * not a two's complement code considering the bit[6:0] is a absolute
39  * distance from the zero point.
40  */
41 union ds4424_raw_data {
42 	struct {
43 		u8 dx:7;
44 		u8 source_bit:1;
45 	};
46 	u8 bits;
47 };
48 
49 enum ds4424_device_ids {
50 	ID_DS4422,
51 	ID_DS4424,
52 };
53 
54 struct ds4424_data {
55 	struct i2c_client *client;
56 	struct mutex lock;
57 	uint8_t save[DS4424_MAX_DAC_CHANNELS];
58 	struct regulator *vcc_reg;
59 	uint8_t raw[DS4424_MAX_DAC_CHANNELS];
60 };
61 
62 static const struct iio_chan_spec ds4424_channels[] = {
63 	DS4424_CHANNEL(0),
64 	DS4424_CHANNEL(1),
65 	DS4424_CHANNEL(2),
66 	DS4424_CHANNEL(3),
67 };
68 
69 static int ds4424_get_value(struct iio_dev *indio_dev,
70 			     int *val, int channel)
71 {
72 	struct ds4424_data *data = iio_priv(indio_dev);
73 	int ret;
74 
75 	mutex_lock(&data->lock);
76 	ret = i2c_smbus_read_byte_data(data->client, DS4424_DAC_ADDR(channel));
77 	if (ret < 0)
78 		goto fail;
79 
80 	*val = ret;
81 
82 fail:
83 	mutex_unlock(&data->lock);
84 	return ret;
85 }
86 
87 static int ds4424_set_value(struct iio_dev *indio_dev,
88 			     int val, struct iio_chan_spec const *chan)
89 {
90 	struct ds4424_data *data = iio_priv(indio_dev);
91 	int ret;
92 
93 	mutex_lock(&data->lock);
94 	ret = i2c_smbus_write_byte_data(data->client,
95 			DS4424_DAC_ADDR(chan->channel), val);
96 	if (ret < 0)
97 		goto fail;
98 
99 	data->raw[chan->channel] = val;
100 
101 fail:
102 	mutex_unlock(&data->lock);
103 	return ret;
104 }
105 
106 static int ds4424_read_raw(struct iio_dev *indio_dev,
107 			   struct iio_chan_spec const *chan,
108 			   int *val, int *val2, long mask)
109 {
110 	union ds4424_raw_data raw;
111 	int ret;
112 
113 	switch (mask) {
114 	case IIO_CHAN_INFO_RAW:
115 		ret = ds4424_get_value(indio_dev, val, chan->channel);
116 		if (ret < 0) {
117 			pr_err("%s : ds4424_get_value returned %d\n",
118 							__func__, ret);
119 			return ret;
120 		}
121 		raw.bits = *val;
122 		*val = raw.dx;
123 		if (raw.source_bit == DS4424_SINK_I)
124 			*val = -*val;
125 		return IIO_VAL_INT;
126 
127 	default:
128 		return -EINVAL;
129 	}
130 }
131 
132 static int ds4424_write_raw(struct iio_dev *indio_dev,
133 			     struct iio_chan_spec const *chan,
134 			     int val, int val2, long mask)
135 {
136 	union ds4424_raw_data raw;
137 
138 	if (val2 != 0)
139 		return -EINVAL;
140 
141 	switch (mask) {
142 	case IIO_CHAN_INFO_RAW:
143 		if (val < S8_MIN || val > S8_MAX)
144 			return -EINVAL;
145 
146 		if (val > 0) {
147 			raw.source_bit = DS4424_SOURCE_I;
148 			raw.dx = val;
149 		} else {
150 			raw.source_bit = DS4424_SINK_I;
151 			raw.dx = -val;
152 		}
153 
154 		return ds4424_set_value(indio_dev, raw.bits, chan);
155 
156 	default:
157 		return -EINVAL;
158 	}
159 }
160 
161 static int ds4424_verify_chip(struct iio_dev *indio_dev)
162 {
163 	int ret, val;
164 
165 	ret = ds4424_get_value(indio_dev, &val, 0);
166 	if (ret < 0)
167 		dev_err(&indio_dev->dev,
168 				"%s failed. ret: %d\n", __func__, ret);
169 
170 	return ret;
171 }
172 
173 static int ds4424_suspend(struct device *dev)
174 {
175 	struct i2c_client *client = to_i2c_client(dev);
176 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
177 	struct ds4424_data *data = iio_priv(indio_dev);
178 	int ret = 0;
179 	int i;
180 
181 	for (i = 0; i < indio_dev->num_channels; i++) {
182 		data->save[i] = data->raw[i];
183 		ret = ds4424_set_value(indio_dev, 0,
184 				&indio_dev->channels[i]);
185 		if (ret < 0)
186 			return ret;
187 	}
188 	return ret;
189 }
190 
191 static int ds4424_resume(struct device *dev)
192 {
193 	struct i2c_client *client = to_i2c_client(dev);
194 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
195 	struct ds4424_data *data = iio_priv(indio_dev);
196 	int ret = 0;
197 	int i;
198 
199 	for (i = 0; i < indio_dev->num_channels; i++) {
200 		ret = ds4424_set_value(indio_dev, data->save[i],
201 				&indio_dev->channels[i]);
202 		if (ret < 0)
203 			return ret;
204 	}
205 	return ret;
206 }
207 
208 static DEFINE_SIMPLE_DEV_PM_OPS(ds4424_pm_ops, ds4424_suspend, ds4424_resume);
209 
210 static const struct iio_info ds4424_info = {
211 	.read_raw = ds4424_read_raw,
212 	.write_raw = ds4424_write_raw,
213 };
214 
215 static int ds4424_probe(struct i2c_client *client)
216 {
217 	const struct i2c_device_id *id = i2c_client_get_device_id(client);
218 	struct ds4424_data *data;
219 	struct iio_dev *indio_dev;
220 	int ret;
221 
222 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
223 	if (!indio_dev)
224 		return -ENOMEM;
225 
226 	data = iio_priv(indio_dev);
227 	i2c_set_clientdata(client, indio_dev);
228 	data->client = client;
229 	indio_dev->name = id->name;
230 
231 	data->vcc_reg = devm_regulator_get(&client->dev, "vcc");
232 	if (IS_ERR(data->vcc_reg))
233 		return dev_err_probe(&client->dev, PTR_ERR(data->vcc_reg),
234 				     "Failed to get vcc-supply regulator.\n");
235 
236 	mutex_init(&data->lock);
237 	ret = regulator_enable(data->vcc_reg);
238 	if (ret < 0) {
239 		dev_err(&client->dev,
240 				"Unable to enable the regulator.\n");
241 		return ret;
242 	}
243 
244 	usleep_range(1000, 1200);
245 	ret = ds4424_verify_chip(indio_dev);
246 	if (ret < 0)
247 		goto fail;
248 
249 	switch (id->driver_data) {
250 	case ID_DS4422:
251 		indio_dev->num_channels = DS4422_MAX_DAC_CHANNELS;
252 		break;
253 	case ID_DS4424:
254 		indio_dev->num_channels = DS4424_MAX_DAC_CHANNELS;
255 		break;
256 	default:
257 		dev_err(&client->dev,
258 				"ds4424: Invalid chip id.\n");
259 		ret = -ENXIO;
260 		goto fail;
261 	}
262 
263 	indio_dev->channels = ds4424_channels;
264 	indio_dev->modes = INDIO_DIRECT_MODE;
265 	indio_dev->info = &ds4424_info;
266 
267 	ret = iio_device_register(indio_dev);
268 	if (ret < 0) {
269 		dev_err(&client->dev,
270 				"iio_device_register failed. ret: %d\n", ret);
271 		goto fail;
272 	}
273 
274 	return ret;
275 
276 fail:
277 	regulator_disable(data->vcc_reg);
278 	return ret;
279 }
280 
281 static void ds4424_remove(struct i2c_client *client)
282 {
283 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
284 	struct ds4424_data *data = iio_priv(indio_dev);
285 
286 	iio_device_unregister(indio_dev);
287 	regulator_disable(data->vcc_reg);
288 }
289 
290 static const struct i2c_device_id ds4424_id[] = {
291 	{ "ds4422", ID_DS4422 },
292 	{ "ds4424", ID_DS4424 },
293 	{ }
294 };
295 
296 MODULE_DEVICE_TABLE(i2c, ds4424_id);
297 
298 static const struct of_device_id ds4424_of_match[] = {
299 	{ .compatible = "maxim,ds4422" },
300 	{ .compatible = "maxim,ds4424" },
301 	{ }
302 };
303 
304 MODULE_DEVICE_TABLE(of, ds4424_of_match);
305 
306 static struct i2c_driver ds4424_driver = {
307 	.driver = {
308 		.name	= "ds4424",
309 		.of_match_table = ds4424_of_match,
310 		.pm     = pm_sleep_ptr(&ds4424_pm_ops),
311 	},
312 	.probe		= ds4424_probe,
313 	.remove		= ds4424_remove,
314 	.id_table	= ds4424_id,
315 };
316 module_i2c_driver(ds4424_driver);
317 
318 MODULE_DESCRIPTION("Maxim DS4424 DAC Driver");
319 MODULE_AUTHOR("Ismail H. Kose <ismail.kose@maximintegrated.com>");
320 MODULE_AUTHOR("Vishal Sood <vishal.sood@maximintegrated.com>");
321 MODULE_AUTHOR("David Jung <david.jung@maximintegrated.com>");
322 MODULE_LICENSE("GPL v2");
323