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>
21 #define DRV_NAME "ad9910"
33 #define DIG_RAMPL 0x0B
34 #define DIG_RAMPS 0x0C
35 #define DIG_RAMPR 0x0D
36 #define SIN_TONEP0 0x0E
37 #define SIN_TONEP1 0x0F
38 #define SIN_TONEP2 0x10
39 #define SIN_TONEP3 0x11
40 #define SIN_TONEP4 0x12
41 #define SIN_TONEP5 0x13
42 #define SIN_TONEP6 0x14
43 #define SIN_TONEP7 0x15
45 #define RAM_ENABLE (1 << 7)
47 #define MANUAL_OSK (1 << 7)
48 #define INVSIC (1 << 6)
49 #define DDS_SINEOP (1)
52 #define OSKEN (1 << 1)
53 #define LOAD_ARR (1 << 2)
54 #define CLR_PHA (1 << 3)
55 #define CLR_DIG (1 << 4)
56 #define ACLR_PHA (1 << 5)
57 #define ACLR_DIG (1 << 6)
58 #define LOAD_LRR (1 << 7)
61 #define SDIO_IPT (1 << 1)
62 #define EXT_PWD (1 << 3)
63 #define ADAC_PWD (1 << 4)
64 #define REFCLK_PWD (1 << 5)
65 #define DAC_PWD (1 << 6)
66 #define DIG_PWD (1 << 7)
70 #define DIGR_LOW (1 << 1)
71 #define DIGR_HIGH (1 << 2)
72 #define DIGR_ENA (1 << 3)
73 #define SYNCCLK_ENA (1 << 6)
74 #define ITER_IOUPD (1 << 7)
76 #define TX_ENA (1 << 1)
77 #define PDCLK_INV (1 << 2)
78 #define PDCLK_ENB (1 << 3)
80 #define PARA_ENA (1 << 4)
81 #define SYNC_DIS (1 << 5)
82 #define DATA_ASS (1 << 6)
83 #define MATCH_ENA (1 << 7)
86 #define PFD_RST (1 << 2)
87 #define REFCLK_RST (1 << 6)
88 #define REFCLK_BYP (1 << 7)
90 /* Register format: 1 byte addr + value */
91 struct ad9910_config
{
111 struct ad9910_state
{
113 struct spi_device
*sdev
;
116 static ssize_t
ad9910_set_parameter(struct device
*dev
,
117 struct device_attribute
*attr
,
121 struct spi_message msg
;
122 struct spi_transfer xfer
;
124 struct ad9910_config
*config
= (struct ad9910_config
*)buf
;
125 struct iio_dev
*idev
= dev_get_drvdata(dev
);
126 struct ad9910_state
*st
= iio_priv(idev
);
129 xfer
.tx_buf
= &config
->auxdac
[0];
130 mutex_lock(&st
->lock
);
132 spi_message_init(&msg
);
133 spi_message_add_tail(&xfer
, &msg
);
134 ret
= spi_sync(st
->sdev
, &msg
);
139 xfer
.tx_buf
= &config
->ioupd
[0];
141 spi_message_init(&msg
);
142 spi_message_add_tail(&xfer
, &msg
);
143 ret
= spi_sync(st
->sdev
, &msg
);
148 xfer
.tx_buf
= &config
->ftw
[0];
150 spi_message_init(&msg
);
151 spi_message_add_tail(&xfer
, &msg
);
152 ret
= spi_sync(st
->sdev
, &msg
);
157 xfer
.tx_buf
= &config
->pow
[0];
159 spi_message_init(&msg
);
160 spi_message_add_tail(&xfer
, &msg
);
161 ret
= spi_sync(st
->sdev
, &msg
);
166 xfer
.tx_buf
= &config
->asf
[0];
168 spi_message_init(&msg
);
169 spi_message_add_tail(&xfer
, &msg
);
170 ret
= spi_sync(st
->sdev
, &msg
);
175 xfer
.tx_buf
= &config
->multc
[0];
177 spi_message_init(&msg
);
178 spi_message_add_tail(&xfer
, &msg
);
179 ret
= spi_sync(st
->sdev
, &msg
);
184 xfer
.tx_buf
= &config
->dig_rampl
[0];
186 spi_message_init(&msg
);
187 spi_message_add_tail(&xfer
, &msg
);
188 ret
= spi_sync(st
->sdev
, &msg
);
193 xfer
.tx_buf
= &config
->dig_ramps
[0];
195 spi_message_init(&msg
);
196 spi_message_add_tail(&xfer
, &msg
);
197 ret
= spi_sync(st
->sdev
, &msg
);
202 xfer
.tx_buf
= &config
->dig_rampr
[0];
204 spi_message_init(&msg
);
205 spi_message_add_tail(&xfer
, &msg
);
206 ret
= spi_sync(st
->sdev
, &msg
);
211 xfer
.tx_buf
= &config
->sin_tonep0
[0];
213 spi_message_init(&msg
);
214 spi_message_add_tail(&xfer
, &msg
);
215 ret
= spi_sync(st
->sdev
, &msg
);
220 xfer
.tx_buf
= &config
->sin_tonep1
[0];
222 spi_message_init(&msg
);
223 spi_message_add_tail(&xfer
, &msg
);
224 ret
= spi_sync(st
->sdev
, &msg
);
229 xfer
.tx_buf
= &config
->sin_tonep2
[0];
231 spi_message_init(&msg
);
232 spi_message_add_tail(&xfer
, &msg
);
233 ret
= spi_sync(st
->sdev
, &msg
);
237 xfer
.tx_buf
= &config
->sin_tonep3
[0];
239 spi_message_init(&msg
);
240 spi_message_add_tail(&xfer
, &msg
);
241 ret
= spi_sync(st
->sdev
, &msg
);
246 xfer
.tx_buf
= &config
->sin_tonep4
[0];
248 spi_message_init(&msg
);
249 spi_message_add_tail(&xfer
, &msg
);
250 ret
= spi_sync(st
->sdev
, &msg
);
255 xfer
.tx_buf
= &config
->sin_tonep5
[0];
257 spi_message_init(&msg
);
258 spi_message_add_tail(&xfer
, &msg
);
259 ret
= spi_sync(st
->sdev
, &msg
);
264 xfer
.tx_buf
= &config
->sin_tonep6
[0];
266 spi_message_init(&msg
);
267 spi_message_add_tail(&xfer
, &msg
);
268 ret
= spi_sync(st
->sdev
, &msg
);
273 xfer
.tx_buf
= &config
->sin_tonep7
[0];
275 spi_message_init(&msg
);
276 spi_message_add_tail(&xfer
, &msg
);
277 ret
= spi_sync(st
->sdev
, &msg
);
281 mutex_unlock(&st
->lock
);
283 return ret
? ret
: len
;
286 static IIO_DEVICE_ATTR(dds
, S_IWUSR
, NULL
, ad9910_set_parameter
, 0);
288 static void ad9910_init(struct ad9910_state
*st
)
290 struct spi_message msg
;
291 struct spi_transfer xfer
;
297 cfr
[2] = MANUAL_OSK
| INVSIC
| DDS_SINEOP
;
298 cfr
[3] = AUTO_OSK
| OSKEN
| ACLR_PHA
| ACLR_DIG
| LOAD_LRR
;
301 mutex_lock(&st
->lock
);
306 spi_message_init(&msg
);
307 spi_message_add_tail(&xfer
, &msg
);
308 ret
= spi_sync(st
->sdev
, &msg
);
314 cfr
[2] = READ_FTW
| DIGR_ENA
| ITER_IOUPD
;
315 cfr
[3] = TX_ENA
| PDCLK_INV
| PDCLK_ENB
;
321 spi_message_init(&msg
);
322 spi_message_add_tail(&xfer
, &msg
);
323 ret
= spi_sync(st
->sdev
, &msg
);
330 cfr
[3] = REFCLK_RST
| REFCLK_BYP
;
336 spi_message_init(&msg
);
337 spi_message_add_tail(&xfer
, &msg
);
338 ret
= spi_sync(st
->sdev
, &msg
);
343 mutex_unlock(&st
->lock
);
349 static struct attribute
*ad9910_attributes
[] = {
350 &iio_dev_attr_dds
.dev_attr
.attr
,
354 static const struct attribute_group ad9910_attribute_group
= {
356 .attrs
= ad9910_attributes
,
359 static const struct iio_info ad9910_info
= {
360 .attrs
= &ad9910_attribute_group
,
361 .driver_module
= THIS_MODULE
,
364 static int __devinit
ad9910_probe(struct spi_device
*spi
)
366 struct ad9910_state
*st
;
367 struct iio_dev
*idev
;
370 idev
= iio_allocate_device(sizeof(*st
));
375 spi_set_drvdata(spi
, idev
);
377 mutex_init(&st
->lock
);
380 idev
->dev
.parent
= &spi
->dev
;
381 idev
->info
= &ad9910_info
;
382 idev
->modes
= INDIO_DIRECT_MODE
;
384 ret
= iio_device_register(idev
);
387 spi
->max_speed_hz
= 2000000;
388 spi
->mode
= SPI_MODE_3
;
389 spi
->bits_per_word
= 8;
395 iio_free_device(idev
);
400 static int __devexit
ad9910_remove(struct spi_device
*spi
)
402 iio_device_unregister(spi_get_drvdata(spi
));
407 static struct spi_driver ad9910_driver
= {
410 .owner
= THIS_MODULE
,
412 .probe
= ad9910_probe
,
413 .remove
= __devexit_p(ad9910_remove
),
416 static __init
int ad9910_spi_init(void)
418 return spi_register_driver(&ad9910_driver
);
420 module_init(ad9910_spi_init
);
422 static __exit
void ad9910_spi_exit(void)
424 spi_unregister_driver(&ad9910_driver
);
426 module_exit(ad9910_spi_exit
);
428 MODULE_AUTHOR("Cliff Cai");
429 MODULE_DESCRIPTION("Analog Devices ad9910 driver");
430 MODULE_LICENSE("GPL v2");