Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: adc: adi-axi-adc: add support for AXI ADC IP core

This change adds support for the Analog Devices Generic AXI ADC IP core.
The IP core is used for interfacing with analog-to-digital (ADC) converters
that require either a high-speed serial interface (JESD204B/C) or a source
synchronous parallel interface (LVDS/CMOS).

Usually, some other interface type (i.e SPI) is used as a control interface
for the actual ADC, while the IP core (controlled via this driver), will
interface to the data-lines of the ADC and handle the streaming of data
into memory via DMA.

Because of this, the AXI ADC driver needs the other SPI-ADC driver to
register with it. The SPI-ADC needs to be register via the SPI framework,
while the AXI ADC registers as a platform driver. The two cannot be ordered
in a hierarchy as both drivers have their own registers, and trying to
organize this [in a hierarchy becomes] problematic when trying to map
memory/registers.

There are some modes where the AXI ADC can operate as standalone ADC, but
those will be implemented at a later point in time.

DocLink: https://wiki.analog.com/resources/fpga/docs/axi_adc_ip

Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Michael Hennerich and committed by
Jonathan Cameron
ef040706 e0fcca9f

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