Merge tag 'dma-mapping-5.15' of git://git.infradead.org/users/hch/dma-mapping
[linux-2.6-microblaze.git] / drivers / iio / dac / ti-dac7612.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * DAC7612 Dual, 12-Bit Serial input Digital-to-Analog Converter
4  *
5  * Copyright 2019 Qtechnology A/S
6  * 2019 Ricardo Ribalda <ribalda@kernel.org>
7  *
8  * Licensed under the GPL-2.
9  */
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/spi/spi.h>
13 #include <linux/gpio/consumer.h>
14 #include <linux/iio/iio.h>
15
16 #define DAC7612_RESOLUTION 12
17 #define DAC7612_ADDRESS 4
18 #define DAC7612_START 5
19
20 struct dac7612 {
21         struct spi_device *spi;
22         struct gpio_desc *loaddacs;
23         uint16_t cache[2];
24
25         /*
26          * Lock to protect the state of the device from potential concurrent
27          * write accesses from userspace. The write operation requires an
28          * SPI write, then toggling of a GPIO, so the lock aims to protect
29          * the sanity of the entire sequence of operation.
30          */
31         struct mutex lock;
32
33         /*
34          * DMA (thus cache coherency maintenance) requires the
35          * transfer buffers to live in their own cache lines.
36          */
37         uint8_t data[2] ____cacheline_aligned;
38 };
39
40 static int dac7612_cmd_single(struct dac7612 *priv, int channel, u16 val)
41 {
42         int ret;
43
44         priv->data[0] = BIT(DAC7612_START) | (channel << DAC7612_ADDRESS);
45         priv->data[0] |= val >> 8;
46         priv->data[1] = val & 0xff;
47
48         priv->cache[channel] = val;
49
50         ret = spi_write(priv->spi, priv->data, sizeof(priv->data));
51         if (ret)
52                 return ret;
53
54         gpiod_set_value(priv->loaddacs, 1);
55         gpiod_set_value(priv->loaddacs, 0);
56
57         return 0;
58 }
59
60 #define dac7612_CHANNEL(chan, name) {                           \
61         .type = IIO_VOLTAGE,                                    \
62         .channel = (chan),                                      \
63         .indexed = 1,                                           \
64         .output = 1,                                            \
65         .datasheet_name = name,                                 \
66         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
67         .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
68 }
69
70 static const struct iio_chan_spec dac7612_channels[] = {
71         dac7612_CHANNEL(0, "OUTA"),
72         dac7612_CHANNEL(1, "OUTB"),
73 };
74
75 static int dac7612_read_raw(struct iio_dev *iio_dev,
76                             const struct iio_chan_spec *chan,
77                             int *val, int *val2, long mask)
78 {
79         struct dac7612 *priv;
80
81         switch (mask) {
82         case IIO_CHAN_INFO_RAW:
83                 priv = iio_priv(iio_dev);
84                 *val = priv->cache[chan->channel];
85                 return IIO_VAL_INT;
86
87         case IIO_CHAN_INFO_SCALE:
88                 *val = 1;
89                 return IIO_VAL_INT;
90
91         default:
92                 return -EINVAL;
93         }
94 }
95
96 static int dac7612_write_raw(struct iio_dev *iio_dev,
97                              const struct iio_chan_spec *chan,
98                              int val, int val2, long mask)
99 {
100         struct dac7612 *priv = iio_priv(iio_dev);
101         int ret;
102
103         if (mask != IIO_CHAN_INFO_RAW)
104                 return -EINVAL;
105
106         if ((val >= BIT(DAC7612_RESOLUTION)) || val < 0 || val2)
107                 return -EINVAL;
108
109         if (val == priv->cache[chan->channel])
110                 return 0;
111
112         mutex_lock(&priv->lock);
113         ret = dac7612_cmd_single(priv, chan->channel, val);
114         mutex_unlock(&priv->lock);
115
116         return ret;
117 }
118
119 static const struct iio_info dac7612_info = {
120         .read_raw = dac7612_read_raw,
121         .write_raw = dac7612_write_raw,
122 };
123
124 static int dac7612_probe(struct spi_device *spi)
125 {
126         struct iio_dev *iio_dev;
127         struct dac7612 *priv;
128         int i;
129         int ret;
130
131         iio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*priv));
132         if (!iio_dev)
133                 return -ENOMEM;
134
135         priv = iio_priv(iio_dev);
136         /*
137          * LOADDACS pin can be controlled by the driver or externally.
138          * When controlled by the driver, the DAC value is updated after
139          * every write.
140          * When the driver does not control the PIN, the user or an external
141          * event can change the value of all DACs by pulsing down the LOADDACs
142          * pin.
143          */
144         priv->loaddacs = devm_gpiod_get_optional(&spi->dev, "ti,loaddacs",
145                                                  GPIOD_OUT_LOW);
146         if (IS_ERR(priv->loaddacs))
147                 return PTR_ERR(priv->loaddacs);
148         priv->spi = spi;
149         spi_set_drvdata(spi, iio_dev);
150         iio_dev->info = &dac7612_info;
151         iio_dev->modes = INDIO_DIRECT_MODE;
152         iio_dev->channels = dac7612_channels;
153         iio_dev->num_channels = ARRAY_SIZE(priv->cache);
154         iio_dev->name = spi_get_device_id(spi)->name;
155
156         mutex_init(&priv->lock);
157
158         for (i = 0; i < ARRAY_SIZE(priv->cache); i++) {
159                 ret = dac7612_cmd_single(priv, i, 0);
160                 if (ret)
161                         return ret;
162         }
163
164         return devm_iio_device_register(&spi->dev, iio_dev);
165 }
166
167 static const struct spi_device_id dac7612_id[] = {
168         {"ti-dac7612"},
169         {}
170 };
171 MODULE_DEVICE_TABLE(spi, dac7612_id);
172
173 static const struct of_device_id dac7612_of_match[] = {
174         { .compatible = "ti,dac7612" },
175         { .compatible = "ti,dac7612u" },
176         { .compatible = "ti,dac7612ub" },
177         { },
178 };
179 MODULE_DEVICE_TABLE(of, dac7612_of_match);
180
181 static struct spi_driver dac7612_driver = {
182         .driver = {
183                    .name = "ti-dac7612",
184                    .of_match_table = dac7612_of_match,
185                    },
186         .probe = dac7612_probe,
187         .id_table = dac7612_id,
188 };
189 module_spi_driver(dac7612_driver);
190
191 MODULE_AUTHOR("Ricardo Ribalda <ribalda@kernel.org>");
192 MODULE_DESCRIPTION("Texas Instruments DAC7612 DAC driver");
193 MODULE_LICENSE("GPL v2");