2 * Driver for ADI Direct Digital Synthesis ad9910
4 * Copyright (c) 2010 Analog Devices Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #include <linux/types.h>
12 #include <linux/mutex.h>
13 #include <linux/device.h>
14 #include <linux/spi/spi.h>
15 #include <linux/slab.h>
16 #include <linux/sysfs.h>
17 #include <linux/module.h>
19 #include <linux/iio/iio.h>
20 #include <linux/iio/sysfs.h>
22 #define DRV_NAME "ad9910"
34 #define DIG_RAMPL 0x0B
35 #define DIG_RAMPS 0x0C
36 #define DIG_RAMPR 0x0D
37 #define SIN_TONEP0 0x0E
38 #define SIN_TONEP1 0x0F
39 #define SIN_TONEP2 0x10
40 #define SIN_TONEP3 0x11
41 #define SIN_TONEP4 0x12
42 #define SIN_TONEP5 0x13
43 #define SIN_TONEP6 0x14
44 #define SIN_TONEP7 0x15
46 #define RAM_ENABLE (1 << 7)
48 #define MANUAL_OSK (1 << 7)
49 #define INVSIC (1 << 6)
50 #define DDS_SINEOP (1)
53 #define OSKEN (1 << 1)
54 #define LOAD_ARR (1 << 2)
55 #define CLR_PHA (1 << 3)
56 #define CLR_DIG (1 << 4)
57 #define ACLR_PHA (1 << 5)
58 #define ACLR_DIG (1 << 6)
59 #define LOAD_LRR (1 << 7)
62 #define SDIO_IPT (1 << 1)
63 #define EXT_PWD (1 << 3)
64 #define ADAC_PWD (1 << 4)
65 #define REFCLK_PWD (1 << 5)
66 #define DAC_PWD (1 << 6)
67 #define DIG_PWD (1 << 7)
71 #define DIGR_LOW (1 << 1)
72 #define DIGR_HIGH (1 << 2)
73 #define DIGR_ENA (1 << 3)
74 #define SYNCCLK_ENA (1 << 6)
75 #define ITER_IOUPD (1 << 7)
77 #define TX_ENA (1 << 1)
78 #define PDCLK_INV (1 << 2)
79 #define PDCLK_ENB (1 << 3)
81 #define PARA_ENA (1 << 4)
82 #define SYNC_DIS (1 << 5)
83 #define DATA_ASS (1 << 6)
84 #define MATCH_ENA (1 << 7)
87 #define PFD_RST (1 << 2)
88 #define REFCLK_RST (1 << 6)
89 #define REFCLK_BYP (1 << 7)
91 /* Register format: 1 byte addr + value */
92 struct ad9910_config {
112 struct ad9910_state {
114 struct spi_device *sdev;
117 static ssize_t ad9910_set_parameter(struct device *dev,
118 struct device_attribute *attr,
122 struct spi_transfer xfer;
124 struct ad9910_config *config = (struct ad9910_config *)buf;
125 struct iio_dev *idev = dev_to_iio_dev(dev);
126 struct ad9910_state *st = iio_priv(idev);
129 xfer.tx_buf = &config->auxdac[0];
130 mutex_lock(&st->lock);
132 ret = spi_sync_transfer(st->sdev, &xfer, 1);
137 xfer.tx_buf = &config->ioupd[0];
139 ret = spi_sync_transfer(st->sdev, &xfer, 1);
144 xfer.tx_buf = &config->ftw[0];
146 ret = spi_sync_transfer(st->sdev, &xfer, 1);
151 xfer.tx_buf = &config->pow[0];
153 ret = spi_sync_transfer(st->sdev, &xfer, 1);
158 xfer.tx_buf = &config->asf[0];
160 ret = spi_sync_transfer(st->sdev, &xfer, 1);
165 xfer.tx_buf = &config->multc[0];
167 ret = spi_sync_transfer(st->sdev, &xfer, 1);
172 xfer.tx_buf = &config->dig_rampl[0];
174 ret = spi_sync_transfer(st->sdev, &xfer, 1);
179 xfer.tx_buf = &config->dig_ramps[0];
181 ret = spi_sync_transfer(st->sdev, &xfer, 1);
186 xfer.tx_buf = &config->dig_rampr[0];
188 ret = spi_sync_transfer(st->sdev, &xfer, 1);
193 xfer.tx_buf = &config->sin_tonep0[0];
195 ret = spi_sync_transfer(st->sdev, &xfer, 1);
200 xfer.tx_buf = &config->sin_tonep1[0];
202 ret = spi_sync_transfer(st->sdev, &xfer, 1);
207 xfer.tx_buf = &config->sin_tonep2[0];
209 ret = spi_sync_transfer(st->sdev, &xfer, 1);
213 xfer.tx_buf = &config->sin_tonep3[0];
215 ret = spi_sync_transfer(st->sdev, &xfer, 1);
220 xfer.tx_buf = &config->sin_tonep4[0];
222 ret = spi_sync_transfer(st->sdev, &xfer, 1);
227 xfer.tx_buf = &config->sin_tonep5[0];
229 ret = spi_sync_transfer(st->sdev, &xfer, 1);
234 xfer.tx_buf = &config->sin_tonep6[0];
236 ret = spi_sync_transfer(st->sdev, &xfer, 1);
241 xfer.tx_buf = &config->sin_tonep7[0];
243 ret = spi_sync_transfer(st->sdev, &xfer, 1);
247 mutex_unlock(&st->lock);
249 return ret ? ret : len;
252 static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9910_set_parameter, 0);
254 static void ad9910_init(struct ad9910_state *st)
256 struct spi_transfer xfer;
262 cfr[2] = MANUAL_OSK | INVSIC | DDS_SINEOP;
263 cfr[3] = AUTO_OSK | OSKEN | ACLR_PHA | ACLR_DIG | LOAD_LRR;
266 mutex_lock(&st->lock);
271 ret = spi_sync_transfer(st->sdev, &xfer, 1);
277 cfr[2] = READ_FTW | DIGR_ENA | ITER_IOUPD;
278 cfr[3] = TX_ENA | PDCLK_INV | PDCLK_ENB;
284 ret = spi_sync_transfer(st->sdev, &xfer, 1);
291 cfr[3] = REFCLK_RST | REFCLK_BYP;
297 ret = spi_sync_transfer(st->sdev, &xfer, 1);
302 mutex_unlock(&st->lock);
308 static struct attribute *ad9910_attributes[] = {
309 &iio_dev_attr_dds.dev_attr.attr,
313 static const struct attribute_group ad9910_attribute_group = {
314 .attrs = ad9910_attributes,
317 static const struct iio_info ad9910_info = {
318 .attrs = &ad9910_attribute_group,
319 .driver_module = THIS_MODULE,
322 static int ad9910_probe(struct spi_device *spi)
324 struct ad9910_state *st;
325 struct iio_dev *idev;
328 idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
331 spi_set_drvdata(spi, idev);
333 mutex_init(&st->lock);
336 idev->dev.parent = &spi->dev;
337 idev->info = &ad9910_info;
338 idev->modes = INDIO_DIRECT_MODE;
340 ret = iio_device_register(idev);
343 spi->max_speed_hz = 2000000;
344 spi->mode = SPI_MODE_3;
345 spi->bits_per_word = 8;
351 static int ad9910_remove(struct spi_device *spi)
353 iio_device_unregister(spi_get_drvdata(spi));
358 static struct spi_driver ad9910_driver = {
361 .owner = THIS_MODULE,
363 .probe = ad9910_probe,
364 .remove = ad9910_remove,
366 module_spi_driver(ad9910_driver);
368 MODULE_AUTHOR("Cliff Cai");
369 MODULE_DESCRIPTION("Analog Devices ad9910 driver");
370 MODULE_LICENSE("GPL v2");
371 MODULE_ALIAS("spi:" DRV_NAME);