1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * AD7606 Parallel Interface ADC driver
4 *
5 * Copyright 2011 - 2024 Analog Devices Inc.
6 * Copyright 2024 BayLibre SAS.
7 */
8
9 #include <linux/err.h>
10 #include <linux/gpio/consumer.h>
11 #include <linux/io.h>
12 #include <linux/mod_devicetable.h>
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/property.h>
16 #include <linux/types.h>
17
18 #include <linux/iio/backend.h>
19 #include <linux/iio/iio.h>
20
21 #include "ad7606.h"
22 #include "ad7606_bus_iface.h"
23
24 static const struct iio_chan_spec ad7606b_bi_channels[] = {
25 AD7606_BI_CHANNEL(0),
26 AD7606_BI_CHANNEL(1),
27 AD7606_BI_CHANNEL(2),
28 AD7606_BI_CHANNEL(3),
29 AD7606_BI_CHANNEL(4),
30 AD7606_BI_CHANNEL(5),
31 AD7606_BI_CHANNEL(6),
32 AD7606_BI_CHANNEL(7),
33 };
34
35 static const struct iio_chan_spec ad7606b_bi_sw_channels[] = {
36 AD7606_BI_SW_CHANNEL(0),
37 AD7606_BI_SW_CHANNEL(1),
38 AD7606_BI_SW_CHANNEL(2),
39 AD7606_BI_SW_CHANNEL(3),
40 AD7606_BI_SW_CHANNEL(4),
41 AD7606_BI_SW_CHANNEL(5),
42 AD7606_BI_SW_CHANNEL(6),
43 AD7606_BI_SW_CHANNEL(7),
44 };
45
ad7606_par_bus_update_scan_mode(struct iio_dev * indio_dev,const unsigned long * scan_mask)46 static int ad7606_par_bus_update_scan_mode(struct iio_dev *indio_dev,
47 const unsigned long *scan_mask)
48 {
49 struct ad7606_state *st = iio_priv(indio_dev);
50 unsigned int c, ret;
51
52 for (c = 0; c < indio_dev->num_channels; c++) {
53 if (test_bit(c, scan_mask))
54 ret = iio_backend_chan_enable(st->back, c);
55 else
56 ret = iio_backend_chan_disable(st->back, c);
57 if (ret)
58 return ret;
59 }
60
61 return 0;
62 }
63
ad7606_par_bus_setup_iio_backend(struct device * dev,struct iio_dev * indio_dev)64 static int ad7606_par_bus_setup_iio_backend(struct device *dev,
65 struct iio_dev *indio_dev)
66 {
67 struct ad7606_state *st = iio_priv(indio_dev);
68 unsigned int ret, c;
69 struct iio_backend_data_fmt data = {
70 .sign_extend = true,
71 .enable = true,
72 };
73
74 st->back = devm_iio_backend_get(dev, NULL);
75 if (IS_ERR(st->back))
76 return PTR_ERR(st->back);
77
78 /* If the device is iio_backend powered the PWM is mandatory */
79 if (!st->cnvst_pwm)
80 return dev_err_probe(st->dev, -EINVAL,
81 "A PWM is mandatory when using backend.\n");
82
83 ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev);
84 if (ret)
85 return ret;
86
87 ret = devm_iio_backend_enable(dev, st->back);
88 if (ret)
89 return ret;
90
91 for (c = 0; c < indio_dev->num_channels; c++) {
92 ret = iio_backend_data_format_set(st->back, c, &data);
93 if (ret)
94 return ret;
95 }
96
97 indio_dev->channels = ad7606b_bi_channels;
98 indio_dev->num_channels = 8;
99
100 return 0;
101 }
102
ad7606_par_bus_reg_read(struct ad7606_state * st,unsigned int addr)103 static int ad7606_par_bus_reg_read(struct ad7606_state *st, unsigned int addr)
104 {
105 struct ad7606_platform_data *pdata = st->dev->platform_data;
106 int val, ret;
107
108 ret = pdata->bus_reg_read(st->back, addr, &val);
109 if (ret)
110 return ret;
111
112 return val;
113 }
114
ad7606_par_bus_reg_write(struct ad7606_state * st,unsigned int addr,unsigned int val)115 static int ad7606_par_bus_reg_write(struct ad7606_state *st, unsigned int addr,
116 unsigned int val)
117 {
118 struct ad7606_platform_data *pdata = st->dev->platform_data;
119
120 return pdata->bus_reg_write(st->back, addr, val);
121 }
122
ad7606_par_bus_sw_mode_config(struct iio_dev * indio_dev)123 static int ad7606_par_bus_sw_mode_config(struct iio_dev *indio_dev)
124 {
125 indio_dev->channels = ad7606b_bi_sw_channels;
126
127 return 0;
128 }
129
130 static const struct ad7606_bus_ops ad7606_bi_bops = {
131 .iio_backend_config = ad7606_par_bus_setup_iio_backend,
132 .update_scan_mode = ad7606_par_bus_update_scan_mode,
133 .reg_read = ad7606_par_bus_reg_read,
134 .reg_write = ad7606_par_bus_reg_write,
135 .sw_mode_config = ad7606_par_bus_sw_mode_config,
136 };
137
ad7606_par16_read_block(struct device * dev,int count,void * buf)138 static int ad7606_par16_read_block(struct device *dev,
139 int count, void *buf)
140 {
141 struct iio_dev *indio_dev = dev_get_drvdata(dev);
142 struct ad7606_state *st = iio_priv(indio_dev);
143
144
145 /*
146 * On the parallel interface, the frstdata signal is set to high while
147 * and after reading the sample of the first channel and low for all
148 * other channels. This can be used to check that the incoming data is
149 * correctly aligned. During normal operation the data should never
150 * become unaligned, but some glitch or electrostatic discharge might
151 * cause an extra read or clock cycle. Monitoring the frstdata signal
152 * allows to recover from such failure situations.
153 */
154 int num = count;
155 u16 *_buf = buf;
156
157 if (st->gpio_frstdata) {
158 insw((unsigned long)st->base_address, _buf, 1);
159 if (!gpiod_get_value(st->gpio_frstdata)) {
160 ad7606_reset(st);
161 return -EIO;
162 }
163 _buf++;
164 num--;
165 }
166 insw((unsigned long)st->base_address, _buf, num);
167 return 0;
168 }
169
170 static const struct ad7606_bus_ops ad7606_par16_bops = {
171 .read_block = ad7606_par16_read_block,
172 };
173
ad7606_par8_read_block(struct device * dev,int count,void * buf)174 static int ad7606_par8_read_block(struct device *dev,
175 int count, void *buf)
176 {
177 struct iio_dev *indio_dev = dev_get_drvdata(dev);
178 struct ad7606_state *st = iio_priv(indio_dev);
179 /*
180 * On the parallel interface, the frstdata signal is set to high while
181 * and after reading the sample of the first channel and low for all
182 * other channels. This can be used to check that the incoming data is
183 * correctly aligned. During normal operation the data should never
184 * become unaligned, but some glitch or electrostatic discharge might
185 * cause an extra read or clock cycle. Monitoring the frstdata signal
186 * allows to recover from such failure situations.
187 */
188 int num = count;
189 u16 *_buf = buf;
190
191 if (st->gpio_frstdata) {
192 insb((unsigned long)st->base_address, _buf, 2);
193 if (!gpiod_get_value(st->gpio_frstdata)) {
194 ad7606_reset(st);
195 return -EIO;
196 }
197 _buf++;
198 num--;
199 }
200 insb((unsigned long)st->base_address, _buf, num * 2);
201
202 return 0;
203 }
204
205 static const struct ad7606_bus_ops ad7606_par8_bops = {
206 .read_block = ad7606_par8_read_block,
207 };
208
ad7606_par_probe(struct platform_device * pdev)209 static int ad7606_par_probe(struct platform_device *pdev)
210 {
211 const struct ad7606_chip_info *chip_info;
212 const struct platform_device_id *id;
213 struct resource *res;
214 void __iomem *addr;
215 resource_size_t remap_size;
216 int irq;
217
218 /*
219 * If a firmware node is available (ACPI or DT), platform_device_id is null
220 * and we must use get_match_data.
221 */
222 if (dev_fwnode(&pdev->dev)) {
223 chip_info = device_get_match_data(&pdev->dev);
224 if (device_property_present(&pdev->dev, "io-backends"))
225 /*
226 * If a backend is available ,call the core probe with backend
227 * bops, otherwise use the former bops.
228 */
229 return ad7606_probe(&pdev->dev, 0, NULL,
230 chip_info,
231 &ad7606_bi_bops);
232 } else {
233 id = platform_get_device_id(pdev);
234 chip_info = (const struct ad7606_chip_info *)id->driver_data;
235 }
236
237 irq = platform_get_irq(pdev, 0);
238 if (irq < 0)
239 return irq;
240
241 addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
242 if (IS_ERR(addr))
243 return PTR_ERR(addr);
244
245 remap_size = resource_size(res);
246
247 return ad7606_probe(&pdev->dev, irq, addr, chip_info,
248 remap_size > 1 ? &ad7606_par16_bops :
249 &ad7606_par8_bops);
250 }
251
252 static const struct platform_device_id ad7606_driver_ids[] = {
253 { .name = "ad7605-4", .driver_data = (kernel_ulong_t)&ad7605_4_info, },
254 { .name = "ad7606-4", .driver_data = (kernel_ulong_t)&ad7606_4_info, },
255 { .name = "ad7606-6", .driver_data = (kernel_ulong_t)&ad7606_6_info, },
256 { .name = "ad7606-8", .driver_data = (kernel_ulong_t)&ad7606_8_info, },
257 { .name = "ad7606b", .driver_data = (kernel_ulong_t)&ad7606b_info, },
258 { .name = "ad7607", .driver_data = (kernel_ulong_t)&ad7607_info, },
259 { .name = "ad7608", .driver_data = (kernel_ulong_t)&ad7608_info, },
260 { .name = "ad7609", .driver_data = (kernel_ulong_t)&ad7609_info, },
261 { }
262 };
263 MODULE_DEVICE_TABLE(platform, ad7606_driver_ids);
264
265 static const struct of_device_id ad7606_of_match[] = {
266 { .compatible = "adi,ad7605-4", .data = &ad7605_4_info },
267 { .compatible = "adi,ad7606-4", .data = &ad7606_4_info },
268 { .compatible = "adi,ad7606-6", .data = &ad7606_6_info },
269 { .compatible = "adi,ad7606-8", .data = &ad7606_8_info },
270 { .compatible = "adi,ad7606b", .data = &ad7606b_info },
271 { .compatible = "adi,ad7607", .data = &ad7607_info },
272 { .compatible = "adi,ad7608", .data = &ad7608_info },
273 { .compatible = "adi,ad7609", .data = &ad7609_info },
274 { }
275 };
276 MODULE_DEVICE_TABLE(of, ad7606_of_match);
277
278 static struct platform_driver ad7606_driver = {
279 .probe = ad7606_par_probe,
280 .id_table = ad7606_driver_ids,
281 .driver = {
282 .name = "ad7606",
283 .pm = AD7606_PM_OPS,
284 .of_match_table = ad7606_of_match,
285 },
286 };
287 module_platform_driver(ad7606_driver);
288
289 MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
290 MODULE_DESCRIPTION("Analog Devices AD7606 ADC");
291 MODULE_LICENSE("GPL v2");
292 MODULE_IMPORT_NS("IIO_AD7606");
293 MODULE_IMPORT_NS("IIO_BACKEND");
294