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