1ef040706SMichael Hennerich // SPDX-License-Identifier: GPL-2.0-only
2ef040706SMichael Hennerich /*
3ef040706SMichael Hennerich * Analog Devices Generic AXI ADC IP core
4ef040706SMichael Hennerich * Link: https://wiki.analog.com/resources/fpga/docs/axi_adc_ip
5ef040706SMichael Hennerich *
6ef040706SMichael Hennerich * Copyright 2012-2020 Analog Devices Inc.
7ef040706SMichael Hennerich */
8ef040706SMichael Hennerich
9ef040706SMichael Hennerich #include <linux/bitfield.h>
10ef040706SMichael Hennerich #include <linux/clk.h>
11d3513f12SNuno Sa #include <linux/err.h>
12ef040706SMichael Hennerich #include <linux/io.h>
13ef040706SMichael Hennerich #include <linux/delay.h>
14ef040706SMichael Hennerich #include <linux/module.h>
151240c94cSRob Herring #include <linux/of.h>
16ef040706SMichael Hennerich #include <linux/platform_device.h>
171240c94cSRob Herring #include <linux/property.h>
18b70042e4SNuno Sa #include <linux/regmap.h>
19ef040706SMichael Hennerich #include <linux/slab.h>
20ef040706SMichael Hennerich
21ef040706SMichael Hennerich #include <linux/fpga/adi-axi-common.h>
22d3513f12SNuno Sa
23d3513f12SNuno Sa #include <linux/iio/backend.h>
24d3513f12SNuno Sa #include <linux/iio/buffer-dmaengine.h>
25d3513f12SNuno Sa #include <linux/iio/buffer.h>
26d3513f12SNuno Sa #include <linux/iio/iio.h>
27ef040706SMichael Hennerich
2863abed2aSJonathan Cameron /*
29ef040706SMichael Hennerich * Register definitions:
30ef040706SMichael Hennerich * https://wiki.analog.com/resources/fpga/docs/axi_adc_ip#register_map
31ef040706SMichael Hennerich */
32ef040706SMichael Hennerich
33ef040706SMichael Hennerich /* ADC controls */
34ef040706SMichael Hennerich
35ef040706SMichael Hennerich #define ADI_AXI_REG_RSTN 0x0040
36ef040706SMichael Hennerich #define ADI_AXI_REG_RSTN_CE_N BIT(2)
37ef040706SMichael Hennerich #define ADI_AXI_REG_RSTN_MMCM_RSTN BIT(1)
38ef040706SMichael Hennerich #define ADI_AXI_REG_RSTN_RSTN BIT(0)
39ef040706SMichael Hennerich
40ef040706SMichael Hennerich /* ADC Channel controls */
41ef040706SMichael Hennerich
42ef040706SMichael Hennerich #define ADI_AXI_REG_CHAN_CTRL(c) (0x0400 + (c) * 0x40)
43ef040706SMichael Hennerich #define ADI_AXI_REG_CHAN_CTRL_LB_OWR BIT(11)
44ef040706SMichael Hennerich #define ADI_AXI_REG_CHAN_CTRL_PN_SEL_OWR BIT(10)
45ef040706SMichael Hennerich #define ADI_AXI_REG_CHAN_CTRL_IQCOR_EN BIT(9)
46ef040706SMichael Hennerich #define ADI_AXI_REG_CHAN_CTRL_DCFILT_EN BIT(8)
47d3513f12SNuno Sa #define ADI_AXI_REG_CHAN_CTRL_FMT_MASK GENMASK(6, 4)
48ef040706SMichael Hennerich #define ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT BIT(6)
49ef040706SMichael Hennerich #define ADI_AXI_REG_CHAN_CTRL_FMT_TYPE BIT(5)
50ef040706SMichael Hennerich #define ADI_AXI_REG_CHAN_CTRL_FMT_EN BIT(4)
51ef040706SMichael Hennerich #define ADI_AXI_REG_CHAN_CTRL_PN_TYPE_OWR BIT(1)
52ef040706SMichael Hennerich #define ADI_AXI_REG_CHAN_CTRL_ENABLE BIT(0)
53ef040706SMichael Hennerich
54ef040706SMichael Hennerich #define ADI_AXI_REG_CHAN_CTRL_DEFAULTS \
55ef040706SMichael Hennerich (ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT | \
56ef040706SMichael Hennerich ADI_AXI_REG_CHAN_CTRL_FMT_EN | \
57ef040706SMichael Hennerich ADI_AXI_REG_CHAN_CTRL_ENABLE)
58ef040706SMichael Hennerich
59ef040706SMichael Hennerich struct adi_axi_adc_state {
60b70042e4SNuno Sa struct regmap *regmap;
61ef040706SMichael Hennerich struct device *dev;
62ef040706SMichael Hennerich };
63ef040706SMichael Hennerich
axi_adc_enable(struct iio_backend * back)64d3513f12SNuno Sa static int axi_adc_enable(struct iio_backend *back)
65ef040706SMichael Hennerich {
66d3513f12SNuno Sa struct adi_axi_adc_state *st = iio_backend_get_priv(back);
67b70042e4SNuno Sa int ret;
68ef040706SMichael Hennerich
69d3513f12SNuno Sa ret = regmap_set_bits(st->regmap, ADI_AXI_REG_RSTN,
70b70042e4SNuno Sa ADI_AXI_REG_RSTN_MMCM_RSTN);
71b70042e4SNuno Sa if (ret)
72b70042e4SNuno Sa return ret;
73b70042e4SNuno Sa
74d3513f12SNuno Sa fsleep(10000);
75d3513f12SNuno Sa return regmap_set_bits(st->regmap, ADI_AXI_REG_RSTN,
76ef040706SMichael Hennerich ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
77ef040706SMichael Hennerich }
78ef040706SMichael Hennerich
axi_adc_disable(struct iio_backend * back)79d3513f12SNuno Sa static void axi_adc_disable(struct iio_backend *back)
80ef040706SMichael Hennerich {
81d3513f12SNuno Sa struct adi_axi_adc_state *st = iio_backend_get_priv(back);
82ef040706SMichael Hennerich
83d3513f12SNuno Sa regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0);
84d3513f12SNuno Sa }
85d3513f12SNuno Sa
axi_adc_data_format_set(struct iio_backend * back,unsigned int chan,const struct iio_backend_data_fmt * data)86d3513f12SNuno Sa static int axi_adc_data_format_set(struct iio_backend *back, unsigned int chan,
87d3513f12SNuno Sa const struct iio_backend_data_fmt *data)
88d3513f12SNuno Sa {
89d3513f12SNuno Sa struct adi_axi_adc_state *st = iio_backend_get_priv(back);
90d3513f12SNuno Sa u32 val;
91d3513f12SNuno Sa
92d3513f12SNuno Sa if (!data->enable)
93d3513f12SNuno Sa return regmap_clear_bits(st->regmap,
94d3513f12SNuno Sa ADI_AXI_REG_CHAN_CTRL(chan),
95d3513f12SNuno Sa ADI_AXI_REG_CHAN_CTRL_FMT_EN);
96d3513f12SNuno Sa
97d3513f12SNuno Sa val = FIELD_PREP(ADI_AXI_REG_CHAN_CTRL_FMT_EN, true);
98d3513f12SNuno Sa if (data->sign_extend)
99d3513f12SNuno Sa val |= FIELD_PREP(ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT, true);
100d3513f12SNuno Sa if (data->type == IIO_BACKEND_OFFSET_BINARY)
101d3513f12SNuno Sa val |= FIELD_PREP(ADI_AXI_REG_CHAN_CTRL_FMT_TYPE, true);
102d3513f12SNuno Sa
103d3513f12SNuno Sa return regmap_update_bits(st->regmap, ADI_AXI_REG_CHAN_CTRL(chan),
104d3513f12SNuno Sa ADI_AXI_REG_CHAN_CTRL_FMT_MASK, val);
105d3513f12SNuno Sa }
106d3513f12SNuno Sa
axi_adc_chan_enable(struct iio_backend * back,unsigned int chan)107d3513f12SNuno Sa static int axi_adc_chan_enable(struct iio_backend *back, unsigned int chan)
108d3513f12SNuno Sa {
109d3513f12SNuno Sa struct adi_axi_adc_state *st = iio_backend_get_priv(back);
110d3513f12SNuno Sa
111d3513f12SNuno Sa return regmap_set_bits(st->regmap, ADI_AXI_REG_CHAN_CTRL(chan),
112d3513f12SNuno Sa ADI_AXI_REG_CHAN_CTRL_ENABLE);
113d3513f12SNuno Sa }
114d3513f12SNuno Sa
axi_adc_chan_disable(struct iio_backend * back,unsigned int chan)115d3513f12SNuno Sa static int axi_adc_chan_disable(struct iio_backend *back, unsigned int chan)
116d3513f12SNuno Sa {
117d3513f12SNuno Sa struct adi_axi_adc_state *st = iio_backend_get_priv(back);
118d3513f12SNuno Sa
119d3513f12SNuno Sa return regmap_clear_bits(st->regmap, ADI_AXI_REG_CHAN_CTRL(chan),
120d3513f12SNuno Sa ADI_AXI_REG_CHAN_CTRL_ENABLE);
121d3513f12SNuno Sa }
122d3513f12SNuno Sa
axi_adc_request_buffer(struct iio_backend * back,struct iio_dev * indio_dev)123d3513f12SNuno Sa static struct iio_buffer *axi_adc_request_buffer(struct iio_backend *back,
124d3513f12SNuno Sa struct iio_dev *indio_dev)
125d3513f12SNuno Sa {
126d3513f12SNuno Sa struct adi_axi_adc_state *st = iio_backend_get_priv(back);
127d3513f12SNuno Sa struct iio_buffer *buffer;
128d3513f12SNuno Sa const char *dma_name;
129d3513f12SNuno Sa int ret;
130d3513f12SNuno Sa
131d3513f12SNuno Sa if (device_property_read_string(st->dev, "dma-names", &dma_name))
132d3513f12SNuno Sa dma_name = "rx";
133d3513f12SNuno Sa
134d3513f12SNuno Sa buffer = iio_dmaengine_buffer_alloc(st->dev, dma_name);
135d3513f12SNuno Sa if (IS_ERR(buffer)) {
136d3513f12SNuno Sa dev_err(st->dev, "Could not get DMA buffer, %ld\n",
137d3513f12SNuno Sa PTR_ERR(buffer));
138d3513f12SNuno Sa return ERR_CAST(buffer);
139d3513f12SNuno Sa }
140d3513f12SNuno Sa
141d3513f12SNuno Sa indio_dev->modes |= INDIO_BUFFER_HARDWARE;
142d3513f12SNuno Sa ret = iio_device_attach_buffer(indio_dev, buffer);
143d3513f12SNuno Sa if (ret)
144d3513f12SNuno Sa return ERR_PTR(ret);
145d3513f12SNuno Sa
146d3513f12SNuno Sa return buffer;
147d3513f12SNuno Sa }
148d3513f12SNuno Sa
axi_adc_free_buffer(struct iio_backend * back,struct iio_buffer * buffer)149d3513f12SNuno Sa static void axi_adc_free_buffer(struct iio_backend *back,
150d3513f12SNuno Sa struct iio_buffer *buffer)
151d3513f12SNuno Sa {
152d3513f12SNuno Sa iio_dmaengine_buffer_free(buffer);
153ef040706SMichael Hennerich }
154ef040706SMichael Hennerich
155b70042e4SNuno Sa static const struct regmap_config axi_adc_regmap_config = {
156b70042e4SNuno Sa .val_bits = 32,
157b70042e4SNuno Sa .reg_bits = 32,
158b70042e4SNuno Sa .reg_stride = 4,
159b70042e4SNuno Sa .max_register = 0x0800,
160b70042e4SNuno Sa };
161b70042e4SNuno Sa
162d3513f12SNuno Sa static const struct iio_backend_ops adi_axi_adc_generic = {
163d3513f12SNuno Sa .enable = axi_adc_enable,
164d3513f12SNuno Sa .disable = axi_adc_disable,
165d3513f12SNuno Sa .data_format_set = axi_adc_data_format_set,
166d3513f12SNuno Sa .chan_enable = axi_adc_chan_enable,
167d3513f12SNuno Sa .chan_disable = axi_adc_chan_disable,
168d3513f12SNuno Sa .request_buffer = axi_adc_request_buffer,
169d3513f12SNuno Sa .free_buffer = axi_adc_free_buffer,
170d3513f12SNuno Sa };
171d3513f12SNuno Sa
adi_axi_adc_probe(struct platform_device * pdev)172ef040706SMichael Hennerich static int adi_axi_adc_probe(struct platform_device *pdev)
173ef040706SMichael Hennerich {
174d3513f12SNuno Sa const unsigned int *expected_ver;
175ef040706SMichael Hennerich struct adi_axi_adc_state *st;
176b70042e4SNuno Sa void __iomem *base;
177ef040706SMichael Hennerich unsigned int ver;
178*955c824dSNuno Sa struct clk *clk;
179ef040706SMichael Hennerich int ret;
180ef040706SMichael Hennerich
181d3513f12SNuno Sa st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL);
182d3513f12SNuno Sa if (!st)
183ef040706SMichael Hennerich return -ENOMEM;
184ef040706SMichael Hennerich
185b70042e4SNuno Sa base = devm_platform_ioremap_resource(pdev, 0);
186b70042e4SNuno Sa if (IS_ERR(base))
187b70042e4SNuno Sa return PTR_ERR(base);
188b70042e4SNuno Sa
189d3513f12SNuno Sa st->dev = &pdev->dev;
190b70042e4SNuno Sa st->regmap = devm_regmap_init_mmio(&pdev->dev, base,
191b70042e4SNuno Sa &axi_adc_regmap_config);
192b70042e4SNuno Sa if (IS_ERR(st->regmap))
193b70042e4SNuno Sa return PTR_ERR(st->regmap);
194ef040706SMichael Hennerich
195d3513f12SNuno Sa expected_ver = device_get_match_data(&pdev->dev);
196d3513f12SNuno Sa if (!expected_ver)
197d3513f12SNuno Sa return -ENODEV;
198ef040706SMichael Hennerich
199*955c824dSNuno Sa clk = devm_clk_get_enabled(&pdev->dev, NULL);
200*955c824dSNuno Sa if (IS_ERR(clk))
201*955c824dSNuno Sa return PTR_ERR(clk);
202*955c824dSNuno Sa
203d3513f12SNuno Sa /*
204d3513f12SNuno Sa * Force disable the core. Up to the frontend to enable us. And we can
205d3513f12SNuno Sa * still read/write registers...
206d3513f12SNuno Sa */
207d3513f12SNuno Sa ret = regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0);
208b70042e4SNuno Sa if (ret)
209b70042e4SNuno Sa return ret;
210ef040706SMichael Hennerich
211b70042e4SNuno Sa ret = regmap_read(st->regmap, ADI_AXI_REG_VERSION, &ver);
212b70042e4SNuno Sa if (ret)
213b70042e4SNuno Sa return ret;
214ef040706SMichael Hennerich
215720d2766SNuno Sa if (ADI_AXI_PCORE_VER_MAJOR(ver) != ADI_AXI_PCORE_VER_MAJOR(*expected_ver)) {
216ef040706SMichael Hennerich dev_err(&pdev->dev,
217720d2766SNuno Sa "Major version mismatch. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
218d3513f12SNuno Sa ADI_AXI_PCORE_VER_MAJOR(*expected_ver),
219d3513f12SNuno Sa ADI_AXI_PCORE_VER_MINOR(*expected_ver),
220d3513f12SNuno Sa ADI_AXI_PCORE_VER_PATCH(*expected_ver),
221ef040706SMichael Hennerich ADI_AXI_PCORE_VER_MAJOR(ver),
222ef040706SMichael Hennerich ADI_AXI_PCORE_VER_MINOR(ver),
223ef040706SMichael Hennerich ADI_AXI_PCORE_VER_PATCH(ver));
224ef040706SMichael Hennerich return -ENODEV;
225ef040706SMichael Hennerich }
226ef040706SMichael Hennerich
227d3513f12SNuno Sa ret = devm_iio_backend_register(&pdev->dev, &adi_axi_adc_generic, st);
228ef040706SMichael Hennerich if (ret)
229ef040706SMichael Hennerich return ret;
230ef040706SMichael Hennerich
231ef040706SMichael Hennerich dev_info(&pdev->dev, "AXI ADC IP core (%d.%.2d.%c) probed\n",
232ef040706SMichael Hennerich ADI_AXI_PCORE_VER_MAJOR(ver),
233ef040706SMichael Hennerich ADI_AXI_PCORE_VER_MINOR(ver),
234ef040706SMichael Hennerich ADI_AXI_PCORE_VER_PATCH(ver));
235ef040706SMichael Hennerich
236ef040706SMichael Hennerich return 0;
237ef040706SMichael Hennerich }
238ef040706SMichael Hennerich
239d3513f12SNuno Sa static unsigned int adi_axi_adc_10_0_a_info = ADI_AXI_PCORE_VER(10, 0, 'a');
240d3513f12SNuno Sa
241ef040706SMichael Hennerich /* Match table for of_platform binding */
242ef040706SMichael Hennerich static const struct of_device_id adi_axi_adc_of_match[] = {
243ef040706SMichael Hennerich { .compatible = "adi,axi-adc-10.0.a", .data = &adi_axi_adc_10_0_a_info },
244ef040706SMichael Hennerich { /* end of list */ }
245ef040706SMichael Hennerich };
246ef040706SMichael Hennerich MODULE_DEVICE_TABLE(of, adi_axi_adc_of_match);
247ef040706SMichael Hennerich
248ef040706SMichael Hennerich static struct platform_driver adi_axi_adc_driver = {
249ef040706SMichael Hennerich .driver = {
250ef040706SMichael Hennerich .name = KBUILD_MODNAME,
251ef040706SMichael Hennerich .of_match_table = adi_axi_adc_of_match,
252ef040706SMichael Hennerich },
253ef040706SMichael Hennerich .probe = adi_axi_adc_probe,
254ef040706SMichael Hennerich };
255ef040706SMichael Hennerich module_platform_driver(adi_axi_adc_driver);
256ef040706SMichael Hennerich
257ef040706SMichael Hennerich MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
258ef040706SMichael Hennerich MODULE_DESCRIPTION("Analog Devices Generic AXI ADC IP core driver");
259ef040706SMichael Hennerich MODULE_LICENSE("GPL v2");
260e1fc56c4SNuno Sa MODULE_IMPORT_NS(IIO_DMAENGINE_BUFFER);
261d3513f12SNuno Sa MODULE_IMPORT_NS(IIO_BACKEND);
262