1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Analog Devices Generic AXI ADC IP core
4*4882a593Smuzhiyun * Link: https://wiki.analog.com/resources/fpga/docs/axi_adc_ip
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright 2012-2020 Analog Devices Inc.
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/bitfield.h>
10*4882a593Smuzhiyun #include <linux/clk.h>
11*4882a593Smuzhiyun #include <linux/io.h>
12*4882a593Smuzhiyun #include <linux/delay.h>
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/of_device.h>
15*4882a593Smuzhiyun #include <linux/platform_device.h>
16*4882a593Smuzhiyun #include <linux/slab.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #include <linux/iio/iio.h>
19*4882a593Smuzhiyun #include <linux/iio/sysfs.h>
20*4882a593Smuzhiyun #include <linux/iio/buffer.h>
21*4882a593Smuzhiyun #include <linux/iio/buffer-dmaengine.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #include <linux/fpga/adi-axi-common.h>
24*4882a593Smuzhiyun #include <linux/iio/adc/adi-axi-adc.h>
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /**
27*4882a593Smuzhiyun * Register definitions:
28*4882a593Smuzhiyun * https://wiki.analog.com/resources/fpga/docs/axi_adc_ip#register_map
29*4882a593Smuzhiyun */
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun /* ADC controls */
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #define ADI_AXI_REG_RSTN 0x0040
34*4882a593Smuzhiyun #define ADI_AXI_REG_RSTN_CE_N BIT(2)
35*4882a593Smuzhiyun #define ADI_AXI_REG_RSTN_MMCM_RSTN BIT(1)
36*4882a593Smuzhiyun #define ADI_AXI_REG_RSTN_RSTN BIT(0)
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun /* ADC Channel controls */
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #define ADI_AXI_REG_CHAN_CTRL(c) (0x0400 + (c) * 0x40)
41*4882a593Smuzhiyun #define ADI_AXI_REG_CHAN_CTRL_LB_OWR BIT(11)
42*4882a593Smuzhiyun #define ADI_AXI_REG_CHAN_CTRL_PN_SEL_OWR BIT(10)
43*4882a593Smuzhiyun #define ADI_AXI_REG_CHAN_CTRL_IQCOR_EN BIT(9)
44*4882a593Smuzhiyun #define ADI_AXI_REG_CHAN_CTRL_DCFILT_EN BIT(8)
45*4882a593Smuzhiyun #define ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT BIT(6)
46*4882a593Smuzhiyun #define ADI_AXI_REG_CHAN_CTRL_FMT_TYPE BIT(5)
47*4882a593Smuzhiyun #define ADI_AXI_REG_CHAN_CTRL_FMT_EN BIT(4)
48*4882a593Smuzhiyun #define ADI_AXI_REG_CHAN_CTRL_PN_TYPE_OWR BIT(1)
49*4882a593Smuzhiyun #define ADI_AXI_REG_CHAN_CTRL_ENABLE BIT(0)
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun #define ADI_AXI_REG_CHAN_CTRL_DEFAULTS \
52*4882a593Smuzhiyun (ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT | \
53*4882a593Smuzhiyun ADI_AXI_REG_CHAN_CTRL_FMT_EN | \
54*4882a593Smuzhiyun ADI_AXI_REG_CHAN_CTRL_ENABLE)
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun struct adi_axi_adc_core_info {
57*4882a593Smuzhiyun unsigned int version;
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun struct adi_axi_adc_state {
61*4882a593Smuzhiyun struct mutex lock;
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun struct adi_axi_adc_client *client;
64*4882a593Smuzhiyun void __iomem *regs;
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun struct adi_axi_adc_client {
68*4882a593Smuzhiyun struct list_head entry;
69*4882a593Smuzhiyun struct adi_axi_adc_conv conv;
70*4882a593Smuzhiyun struct adi_axi_adc_state *state;
71*4882a593Smuzhiyun struct device *dev;
72*4882a593Smuzhiyun const struct adi_axi_adc_core_info *info;
73*4882a593Smuzhiyun };
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun static LIST_HEAD(registered_clients);
76*4882a593Smuzhiyun static DEFINE_MUTEX(registered_clients_lock);
77*4882a593Smuzhiyun
conv_to_client(struct adi_axi_adc_conv * conv)78*4882a593Smuzhiyun static struct adi_axi_adc_client *conv_to_client(struct adi_axi_adc_conv *conv)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun return container_of(conv, struct adi_axi_adc_client, conv);
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
adi_axi_adc_conv_priv(struct adi_axi_adc_conv * conv)83*4882a593Smuzhiyun void *adi_axi_adc_conv_priv(struct adi_axi_adc_conv *conv)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun struct adi_axi_adc_client *cl = conv_to_client(conv);
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun return (char *)cl + ALIGN(sizeof(struct adi_axi_adc_client), IIO_ALIGN);
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(adi_axi_adc_conv_priv);
90*4882a593Smuzhiyun
adi_axi_adc_write(struct adi_axi_adc_state * st,unsigned int reg,unsigned int val)91*4882a593Smuzhiyun static void adi_axi_adc_write(struct adi_axi_adc_state *st,
92*4882a593Smuzhiyun unsigned int reg,
93*4882a593Smuzhiyun unsigned int val)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun iowrite32(val, st->regs + reg);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
adi_axi_adc_read(struct adi_axi_adc_state * st,unsigned int reg)98*4882a593Smuzhiyun static unsigned int adi_axi_adc_read(struct adi_axi_adc_state *st,
99*4882a593Smuzhiyun unsigned int reg)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun return ioread32(st->regs + reg);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
adi_axi_adc_config_dma_buffer(struct device * dev,struct iio_dev * indio_dev)104*4882a593Smuzhiyun static int adi_axi_adc_config_dma_buffer(struct device *dev,
105*4882a593Smuzhiyun struct iio_dev *indio_dev)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun struct iio_buffer *buffer;
108*4882a593Smuzhiyun const char *dma_name;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun if (!device_property_present(dev, "dmas"))
111*4882a593Smuzhiyun return 0;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun if (device_property_read_string(dev, "dma-names", &dma_name))
114*4882a593Smuzhiyun dma_name = "rx";
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun buffer = devm_iio_dmaengine_buffer_alloc(indio_dev->dev.parent,
117*4882a593Smuzhiyun dma_name);
118*4882a593Smuzhiyun if (IS_ERR(buffer))
119*4882a593Smuzhiyun return PTR_ERR(buffer);
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun indio_dev->modes |= INDIO_BUFFER_HARDWARE;
122*4882a593Smuzhiyun iio_device_attach_buffer(indio_dev, buffer);
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun return 0;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
adi_axi_adc_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)127*4882a593Smuzhiyun static int adi_axi_adc_read_raw(struct iio_dev *indio_dev,
128*4882a593Smuzhiyun struct iio_chan_spec const *chan,
129*4882a593Smuzhiyun int *val, int *val2, long mask)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun struct adi_axi_adc_state *st = iio_priv(indio_dev);
132*4882a593Smuzhiyun struct adi_axi_adc_conv *conv = &st->client->conv;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun if (!conv->read_raw)
135*4882a593Smuzhiyun return -EOPNOTSUPP;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun return conv->read_raw(conv, chan, val, val2, mask);
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
adi_axi_adc_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)140*4882a593Smuzhiyun static int adi_axi_adc_write_raw(struct iio_dev *indio_dev,
141*4882a593Smuzhiyun struct iio_chan_spec const *chan,
142*4882a593Smuzhiyun int val, int val2, long mask)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun struct adi_axi_adc_state *st = iio_priv(indio_dev);
145*4882a593Smuzhiyun struct adi_axi_adc_conv *conv = &st->client->conv;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun if (!conv->write_raw)
148*4882a593Smuzhiyun return -EOPNOTSUPP;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun return conv->write_raw(conv, chan, val, val2, mask);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
adi_axi_adc_update_scan_mode(struct iio_dev * indio_dev,const unsigned long * scan_mask)153*4882a593Smuzhiyun static int adi_axi_adc_update_scan_mode(struct iio_dev *indio_dev,
154*4882a593Smuzhiyun const unsigned long *scan_mask)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun struct adi_axi_adc_state *st = iio_priv(indio_dev);
157*4882a593Smuzhiyun struct adi_axi_adc_conv *conv = &st->client->conv;
158*4882a593Smuzhiyun unsigned int i, ctrl;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun for (i = 0; i < conv->chip_info->num_channels; i++) {
161*4882a593Smuzhiyun ctrl = adi_axi_adc_read(st, ADI_AXI_REG_CHAN_CTRL(i));
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun if (test_bit(i, scan_mask))
164*4882a593Smuzhiyun ctrl |= ADI_AXI_REG_CHAN_CTRL_ENABLE;
165*4882a593Smuzhiyun else
166*4882a593Smuzhiyun ctrl &= ~ADI_AXI_REG_CHAN_CTRL_ENABLE;
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun adi_axi_adc_write(st, ADI_AXI_REG_CHAN_CTRL(i), ctrl);
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun return 0;
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun
adi_axi_adc_conv_register(struct device * dev,size_t sizeof_priv)174*4882a593Smuzhiyun static struct adi_axi_adc_conv *adi_axi_adc_conv_register(struct device *dev,
175*4882a593Smuzhiyun size_t sizeof_priv)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun struct adi_axi_adc_client *cl;
178*4882a593Smuzhiyun size_t alloc_size;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun alloc_size = ALIGN(sizeof(struct adi_axi_adc_client), IIO_ALIGN);
181*4882a593Smuzhiyun if (sizeof_priv)
182*4882a593Smuzhiyun alloc_size += ALIGN(sizeof_priv, IIO_ALIGN);
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun cl = kzalloc(alloc_size, GFP_KERNEL);
185*4882a593Smuzhiyun if (!cl)
186*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun mutex_lock(®istered_clients_lock);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun cl->dev = get_device(dev);
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun list_add_tail(&cl->entry, ®istered_clients);
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun mutex_unlock(®istered_clients_lock);
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun return &cl->conv;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
adi_axi_adc_conv_unregister(struct adi_axi_adc_conv * conv)199*4882a593Smuzhiyun static void adi_axi_adc_conv_unregister(struct adi_axi_adc_conv *conv)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun struct adi_axi_adc_client *cl = conv_to_client(conv);
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun mutex_lock(®istered_clients_lock);
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun list_del(&cl->entry);
206*4882a593Smuzhiyun put_device(cl->dev);
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun mutex_unlock(®istered_clients_lock);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun kfree(cl);
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
devm_adi_axi_adc_conv_release(struct device * dev,void * res)213*4882a593Smuzhiyun static void devm_adi_axi_adc_conv_release(struct device *dev, void *res)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun adi_axi_adc_conv_unregister(*(struct adi_axi_adc_conv **)res);
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
devm_adi_axi_adc_conv_register(struct device * dev,size_t sizeof_priv)218*4882a593Smuzhiyun struct adi_axi_adc_conv *devm_adi_axi_adc_conv_register(struct device *dev,
219*4882a593Smuzhiyun size_t sizeof_priv)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun struct adi_axi_adc_conv **ptr, *conv;
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun ptr = devres_alloc(devm_adi_axi_adc_conv_release, sizeof(*ptr),
224*4882a593Smuzhiyun GFP_KERNEL);
225*4882a593Smuzhiyun if (!ptr)
226*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun conv = adi_axi_adc_conv_register(dev, sizeof_priv);
229*4882a593Smuzhiyun if (IS_ERR(conv)) {
230*4882a593Smuzhiyun devres_free(ptr);
231*4882a593Smuzhiyun return ERR_CAST(conv);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun *ptr = conv;
235*4882a593Smuzhiyun devres_add(dev, ptr);
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun return conv;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(devm_adi_axi_adc_conv_register);
240*4882a593Smuzhiyun
in_voltage_scale_available_show(struct device * dev,struct device_attribute * attr,char * buf)241*4882a593Smuzhiyun static ssize_t in_voltage_scale_available_show(struct device *dev,
242*4882a593Smuzhiyun struct device_attribute *attr,
243*4882a593Smuzhiyun char *buf)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun struct iio_dev *indio_dev = dev_to_iio_dev(dev);
246*4882a593Smuzhiyun struct adi_axi_adc_state *st = iio_priv(indio_dev);
247*4882a593Smuzhiyun struct adi_axi_adc_conv *conv = &st->client->conv;
248*4882a593Smuzhiyun size_t len = 0;
249*4882a593Smuzhiyun int i;
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun for (i = 0; i < conv->chip_info->num_scales; i++) {
252*4882a593Smuzhiyun const unsigned int *s = conv->chip_info->scale_table[i];
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len,
255*4882a593Smuzhiyun "%u.%06u ", s[0], s[1]);
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun buf[len - 1] = '\n';
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun return len;
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0);
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun enum {
265*4882a593Smuzhiyun ADI_AXI_ATTR_SCALE_AVAIL,
266*4882a593Smuzhiyun };
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun #define ADI_AXI_ATTR(_en_, _file_) \
269*4882a593Smuzhiyun [ADI_AXI_ATTR_##_en_] = &iio_dev_attr_##_file_.dev_attr.attr
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun static struct attribute *adi_axi_adc_attributes[] = {
272*4882a593Smuzhiyun ADI_AXI_ATTR(SCALE_AVAIL, in_voltage_scale_available),
273*4882a593Smuzhiyun NULL
274*4882a593Smuzhiyun };
275*4882a593Smuzhiyun
axi_adc_attr_is_visible(struct kobject * kobj,struct attribute * attr,int n)276*4882a593Smuzhiyun static umode_t axi_adc_attr_is_visible(struct kobject *kobj,
277*4882a593Smuzhiyun struct attribute *attr, int n)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun struct device *dev = kobj_to_dev(kobj);
280*4882a593Smuzhiyun struct iio_dev *indio_dev = dev_to_iio_dev(dev);
281*4882a593Smuzhiyun struct adi_axi_adc_state *st = iio_priv(indio_dev);
282*4882a593Smuzhiyun struct adi_axi_adc_conv *conv = &st->client->conv;
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun switch (n) {
285*4882a593Smuzhiyun case ADI_AXI_ATTR_SCALE_AVAIL:
286*4882a593Smuzhiyun if (!conv->chip_info->num_scales)
287*4882a593Smuzhiyun return 0;
288*4882a593Smuzhiyun return attr->mode;
289*4882a593Smuzhiyun default:
290*4882a593Smuzhiyun return attr->mode;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun static const struct attribute_group adi_axi_adc_attribute_group = {
295*4882a593Smuzhiyun .attrs = adi_axi_adc_attributes,
296*4882a593Smuzhiyun .is_visible = axi_adc_attr_is_visible,
297*4882a593Smuzhiyun };
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun static const struct iio_info adi_axi_adc_info = {
300*4882a593Smuzhiyun .read_raw = &adi_axi_adc_read_raw,
301*4882a593Smuzhiyun .write_raw = &adi_axi_adc_write_raw,
302*4882a593Smuzhiyun .attrs = &adi_axi_adc_attribute_group,
303*4882a593Smuzhiyun .update_scan_mode = &adi_axi_adc_update_scan_mode,
304*4882a593Smuzhiyun };
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun static const struct adi_axi_adc_core_info adi_axi_adc_10_0_a_info = {
307*4882a593Smuzhiyun .version = ADI_AXI_PCORE_VER(10, 0, 'a'),
308*4882a593Smuzhiyun };
309*4882a593Smuzhiyun
adi_axi_adc_attach_client(struct device * dev)310*4882a593Smuzhiyun static struct adi_axi_adc_client *adi_axi_adc_attach_client(struct device *dev)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun const struct adi_axi_adc_core_info *info;
313*4882a593Smuzhiyun struct adi_axi_adc_client *cl;
314*4882a593Smuzhiyun struct device_node *cln;
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun info = of_device_get_match_data(dev);
317*4882a593Smuzhiyun if (!info)
318*4882a593Smuzhiyun return ERR_PTR(-ENODEV);
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun cln = of_parse_phandle(dev->of_node, "adi,adc-dev", 0);
321*4882a593Smuzhiyun if (!cln) {
322*4882a593Smuzhiyun dev_err(dev, "No 'adi,adc-dev' node defined\n");
323*4882a593Smuzhiyun return ERR_PTR(-ENODEV);
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun mutex_lock(®istered_clients_lock);
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun list_for_each_entry(cl, ®istered_clients, entry) {
329*4882a593Smuzhiyun if (!cl->dev)
330*4882a593Smuzhiyun continue;
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun if (cl->dev->of_node != cln)
333*4882a593Smuzhiyun continue;
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun if (!try_module_get(cl->dev->driver->owner)) {
336*4882a593Smuzhiyun mutex_unlock(®istered_clients_lock);
337*4882a593Smuzhiyun of_node_put(cln);
338*4882a593Smuzhiyun return ERR_PTR(-ENODEV);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun get_device(cl->dev);
342*4882a593Smuzhiyun cl->info = info;
343*4882a593Smuzhiyun mutex_unlock(®istered_clients_lock);
344*4882a593Smuzhiyun of_node_put(cln);
345*4882a593Smuzhiyun return cl;
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun mutex_unlock(®istered_clients_lock);
349*4882a593Smuzhiyun of_node_put(cln);
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun return ERR_PTR(-EPROBE_DEFER);
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun
adi_axi_adc_setup_channels(struct device * dev,struct adi_axi_adc_state * st)354*4882a593Smuzhiyun static int adi_axi_adc_setup_channels(struct device *dev,
355*4882a593Smuzhiyun struct adi_axi_adc_state *st)
356*4882a593Smuzhiyun {
357*4882a593Smuzhiyun struct adi_axi_adc_conv *conv = &st->client->conv;
358*4882a593Smuzhiyun int i, ret;
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun if (conv->preenable_setup) {
361*4882a593Smuzhiyun ret = conv->preenable_setup(conv);
362*4882a593Smuzhiyun if (ret)
363*4882a593Smuzhiyun return ret;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun for (i = 0; i < conv->chip_info->num_channels; i++) {
367*4882a593Smuzhiyun adi_axi_adc_write(st, ADI_AXI_REG_CHAN_CTRL(i),
368*4882a593Smuzhiyun ADI_AXI_REG_CHAN_CTRL_DEFAULTS);
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun return 0;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
axi_adc_reset(struct adi_axi_adc_state * st)374*4882a593Smuzhiyun static void axi_adc_reset(struct adi_axi_adc_state *st)
375*4882a593Smuzhiyun {
376*4882a593Smuzhiyun adi_axi_adc_write(st, ADI_AXI_REG_RSTN, 0);
377*4882a593Smuzhiyun mdelay(10);
378*4882a593Smuzhiyun adi_axi_adc_write(st, ADI_AXI_REG_RSTN, ADI_AXI_REG_RSTN_MMCM_RSTN);
379*4882a593Smuzhiyun mdelay(10);
380*4882a593Smuzhiyun adi_axi_adc_write(st, ADI_AXI_REG_RSTN,
381*4882a593Smuzhiyun ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun
adi_axi_adc_cleanup(void * data)384*4882a593Smuzhiyun static void adi_axi_adc_cleanup(void *data)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun struct adi_axi_adc_client *cl = data;
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun put_device(cl->dev);
389*4882a593Smuzhiyun module_put(cl->dev->driver->owner);
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
adi_axi_adc_probe(struct platform_device * pdev)392*4882a593Smuzhiyun static int adi_axi_adc_probe(struct platform_device *pdev)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun struct adi_axi_adc_conv *conv;
395*4882a593Smuzhiyun struct iio_dev *indio_dev;
396*4882a593Smuzhiyun struct adi_axi_adc_client *cl;
397*4882a593Smuzhiyun struct adi_axi_adc_state *st;
398*4882a593Smuzhiyun unsigned int ver;
399*4882a593Smuzhiyun int ret;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun cl = adi_axi_adc_attach_client(&pdev->dev);
402*4882a593Smuzhiyun if (IS_ERR(cl))
403*4882a593Smuzhiyun return PTR_ERR(cl);
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun ret = devm_add_action_or_reset(&pdev->dev, adi_axi_adc_cleanup, cl);
406*4882a593Smuzhiyun if (ret)
407*4882a593Smuzhiyun return ret;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
410*4882a593Smuzhiyun if (indio_dev == NULL)
411*4882a593Smuzhiyun return -ENOMEM;
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun st = iio_priv(indio_dev);
414*4882a593Smuzhiyun st->client = cl;
415*4882a593Smuzhiyun cl->state = st;
416*4882a593Smuzhiyun mutex_init(&st->lock);
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun st->regs = devm_platform_ioremap_resource(pdev, 0);
419*4882a593Smuzhiyun if (IS_ERR(st->regs))
420*4882a593Smuzhiyun return PTR_ERR(st->regs);
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun conv = &st->client->conv;
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun axi_adc_reset(st);
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun ver = adi_axi_adc_read(st, ADI_AXI_REG_VERSION);
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun if (cl->info->version > ver) {
429*4882a593Smuzhiyun dev_err(&pdev->dev,
430*4882a593Smuzhiyun "IP core version is too old. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
431*4882a593Smuzhiyun ADI_AXI_PCORE_VER_MAJOR(cl->info->version),
432*4882a593Smuzhiyun ADI_AXI_PCORE_VER_MINOR(cl->info->version),
433*4882a593Smuzhiyun ADI_AXI_PCORE_VER_PATCH(cl->info->version),
434*4882a593Smuzhiyun ADI_AXI_PCORE_VER_MAJOR(ver),
435*4882a593Smuzhiyun ADI_AXI_PCORE_VER_MINOR(ver),
436*4882a593Smuzhiyun ADI_AXI_PCORE_VER_PATCH(ver));
437*4882a593Smuzhiyun return -ENODEV;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun indio_dev->info = &adi_axi_adc_info;
441*4882a593Smuzhiyun indio_dev->name = "adi-axi-adc";
442*4882a593Smuzhiyun indio_dev->modes = INDIO_DIRECT_MODE;
443*4882a593Smuzhiyun indio_dev->num_channels = conv->chip_info->num_channels;
444*4882a593Smuzhiyun indio_dev->channels = conv->chip_info->channels;
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun ret = adi_axi_adc_config_dma_buffer(&pdev->dev, indio_dev);
447*4882a593Smuzhiyun if (ret)
448*4882a593Smuzhiyun return ret;
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun ret = adi_axi_adc_setup_channels(&pdev->dev, st);
451*4882a593Smuzhiyun if (ret)
452*4882a593Smuzhiyun return ret;
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun ret = devm_iio_device_register(&pdev->dev, indio_dev);
455*4882a593Smuzhiyun if (ret)
456*4882a593Smuzhiyun return ret;
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun dev_info(&pdev->dev, "AXI ADC IP core (%d.%.2d.%c) probed\n",
459*4882a593Smuzhiyun ADI_AXI_PCORE_VER_MAJOR(ver),
460*4882a593Smuzhiyun ADI_AXI_PCORE_VER_MINOR(ver),
461*4882a593Smuzhiyun ADI_AXI_PCORE_VER_PATCH(ver));
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun return 0;
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun /* Match table for of_platform binding */
467*4882a593Smuzhiyun static const struct of_device_id adi_axi_adc_of_match[] = {
468*4882a593Smuzhiyun { .compatible = "adi,axi-adc-10.0.a", .data = &adi_axi_adc_10_0_a_info },
469*4882a593Smuzhiyun { /* end of list */ }
470*4882a593Smuzhiyun };
471*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, adi_axi_adc_of_match);
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun static struct platform_driver adi_axi_adc_driver = {
474*4882a593Smuzhiyun .driver = {
475*4882a593Smuzhiyun .name = KBUILD_MODNAME,
476*4882a593Smuzhiyun .of_match_table = adi_axi_adc_of_match,
477*4882a593Smuzhiyun },
478*4882a593Smuzhiyun .probe = adi_axi_adc_probe,
479*4882a593Smuzhiyun };
480*4882a593Smuzhiyun module_platform_driver(adi_axi_adc_driver);
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
483*4882a593Smuzhiyun MODULE_DESCRIPTION("Analog Devices Generic AXI ADC IP core driver");
484*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
485