1 /*
2  * Driver for ADI Direct Digital Synthesis ad9910
3  *
4  * Copyright (c) 2010 Analog Devices Inc.
5  *
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.
9  *
10  */
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>
18 
19 #include "../iio.h"
20 #include "../sysfs.h"
21 
22 #define DRV_NAME "ad9910"
23 
24 #define CFR1 0x0
25 #define CFR2 0x1
26 #define CFR3 0x2
27 
28 #define AUXDAC 0x3
29 #define IOUPD 0x4
30 #define FTW 0x7
31 #define POW 0x8
32 #define ASF 0x9
33 #define MULTC 0x0A
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
45 
46 #define RAM_ENABLE	(1 << 7)
47 
48 #define MANUAL_OSK	(1 << 7)
49 #define INVSIC		(1 << 6)
50 #define DDS_SINEOP	(1)
51 
52 #define AUTO_OSK	(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)
60 
61 #define LSB_FST		(1)
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)
68 
69 #define ENA_AMP		(1)
70 #define READ_FTW	(1)
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)
76 
77 #define TX_ENA		(1 << 1)
78 #define PDCLK_INV	(1 << 2)
79 #define PDCLK_ENB	(1 << 3)
80 
81 #define PARA_ENA	(1 << 4)
82 #define SYNC_DIS	(1 << 5)
83 #define DATA_ASS	(1 << 6)
84 #define MATCH_ENA	(1 << 7)
85 
86 #define PLL_ENA		(1)
87 #define PFD_RST		(1 << 2)
88 #define REFCLK_RST	(1 << 6)
89 #define REFCLK_BYP	(1 << 7)
90 
91 /* Register format: 1 byte addr + value */
92 struct ad9910_config {
93 	u8 auxdac[5];
94 	u8 ioupd[5];
95 	u8 ftw[5];
96 	u8 pow[3];
97 	u8 asf[5];
98 	u8 multc[5];
99 	u8 dig_rampl[9];
100 	u8 dig_ramps[9];
101 	u8 dig_rampr[5];
102 	u8 sin_tonep0[9];
103 	u8 sin_tonep1[9];
104 	u8 sin_tonep2[9];
105 	u8 sin_tonep3[9];
106 	u8 sin_tonep4[9];
107 	u8 sin_tonep5[9];
108 	u8 sin_tonep6[9];
109 	u8 sin_tonep7[9];
110 };
111 
112 struct ad9910_state {
113 	struct mutex lock;
114 	struct spi_device *sdev;
115 };
116 
ad9910_set_parameter(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)117 static ssize_t ad9910_set_parameter(struct device *dev,
118 					struct device_attribute *attr,
119 					const char *buf,
120 					size_t len)
121 {
122 	struct spi_message msg;
123 	struct spi_transfer xfer;
124 	int ret;
125 	struct ad9910_config *config = (struct ad9910_config *)buf;
126 	struct iio_dev *idev = dev_get_drvdata(dev);
127 	struct ad9910_state *st = iio_priv(idev);
128 
129 	xfer.len = 5;
130 	xfer.tx_buf = &config->auxdac[0];
131 	mutex_lock(&st->lock);
132 
133 	spi_message_init(&msg);
134 	spi_message_add_tail(&xfer, &msg);
135 	ret = spi_sync(st->sdev, &msg);
136 	if (ret)
137 		goto error_ret;
138 
139 	xfer.len = 5;
140 	xfer.tx_buf = &config->ioupd[0];
141 
142 	spi_message_init(&msg);
143 	spi_message_add_tail(&xfer, &msg);
144 	ret = spi_sync(st->sdev, &msg);
145 	if (ret)
146 		goto error_ret;
147 
148 	xfer.len = 5;
149 	xfer.tx_buf = &config->ftw[0];
150 
151 	spi_message_init(&msg);
152 	spi_message_add_tail(&xfer, &msg);
153 	ret = spi_sync(st->sdev, &msg);
154 	if (ret)
155 		goto error_ret;
156 
157 	xfer.len = 3;
158 	xfer.tx_buf = &config->pow[0];
159 
160 	spi_message_init(&msg);
161 	spi_message_add_tail(&xfer, &msg);
162 	ret = spi_sync(st->sdev, &msg);
163 	if (ret)
164 		goto error_ret;
165 
166 	xfer.len = 5;
167 	xfer.tx_buf = &config->asf[0];
168 
169 	spi_message_init(&msg);
170 	spi_message_add_tail(&xfer, &msg);
171 	ret = spi_sync(st->sdev, &msg);
172 	if (ret)
173 		goto error_ret;
174 
175 	xfer.len = 5;
176 	xfer.tx_buf = &config->multc[0];
177 
178 	spi_message_init(&msg);
179 	spi_message_add_tail(&xfer, &msg);
180 	ret = spi_sync(st->sdev, &msg);
181 	if (ret)
182 		goto error_ret;
183 
184 	xfer.len = 9;
185 	xfer.tx_buf = &config->dig_rampl[0];
186 
187 	spi_message_init(&msg);
188 	spi_message_add_tail(&xfer, &msg);
189 	ret = spi_sync(st->sdev, &msg);
190 	if (ret)
191 		goto error_ret;
192 
193 	xfer.len = 9;
194 	xfer.tx_buf = &config->dig_ramps[0];
195 
196 	spi_message_init(&msg);
197 	spi_message_add_tail(&xfer, &msg);
198 	ret = spi_sync(st->sdev, &msg);
199 	if (ret)
200 		goto error_ret;
201 
202 	xfer.len = 5;
203 	xfer.tx_buf = &config->dig_rampr[0];
204 
205 	spi_message_init(&msg);
206 	spi_message_add_tail(&xfer, &msg);
207 	ret = spi_sync(st->sdev, &msg);
208 	if (ret)
209 		goto error_ret;
210 
211 	xfer.len = 9;
212 	xfer.tx_buf = &config->sin_tonep0[0];
213 
214 	spi_message_init(&msg);
215 	spi_message_add_tail(&xfer, &msg);
216 	ret = spi_sync(st->sdev, &msg);
217 	if (ret)
218 		goto error_ret;
219 
220 	xfer.len = 9;
221 	xfer.tx_buf = &config->sin_tonep1[0];
222 
223 	spi_message_init(&msg);
224 	spi_message_add_tail(&xfer, &msg);
225 	ret = spi_sync(st->sdev, &msg);
226 	if (ret)
227 		goto error_ret;
228 
229 	xfer.len = 9;
230 	xfer.tx_buf = &config->sin_tonep2[0];
231 
232 	spi_message_init(&msg);
233 	spi_message_add_tail(&xfer, &msg);
234 	ret = spi_sync(st->sdev, &msg);
235 	if (ret)
236 		goto error_ret;
237 	xfer.len = 9;
238 	xfer.tx_buf = &config->sin_tonep3[0];
239 
240 	spi_message_init(&msg);
241 	spi_message_add_tail(&xfer, &msg);
242 	ret = spi_sync(st->sdev, &msg);
243 	if (ret)
244 		goto error_ret;
245 
246 	xfer.len = 9;
247 	xfer.tx_buf = &config->sin_tonep4[0];
248 
249 	spi_message_init(&msg);
250 	spi_message_add_tail(&xfer, &msg);
251 	ret = spi_sync(st->sdev, &msg);
252 	if (ret)
253 		goto error_ret;
254 
255 	xfer.len = 9;
256 	xfer.tx_buf = &config->sin_tonep5[0];
257 
258 	spi_message_init(&msg);
259 	spi_message_add_tail(&xfer, &msg);
260 	ret = spi_sync(st->sdev, &msg);
261 	if (ret)
262 		goto error_ret;
263 
264 	xfer.len = 9;
265 	xfer.tx_buf = &config->sin_tonep6[0];
266 
267 	spi_message_init(&msg);
268 	spi_message_add_tail(&xfer, &msg);
269 	ret = spi_sync(st->sdev, &msg);
270 	if (ret)
271 		goto error_ret;
272 
273 	xfer.len = 9;
274 	xfer.tx_buf = &config->sin_tonep7[0];
275 
276 	spi_message_init(&msg);
277 	spi_message_add_tail(&xfer, &msg);
278 	ret = spi_sync(st->sdev, &msg);
279 	if (ret)
280 		goto error_ret;
281 error_ret:
282 	mutex_unlock(&st->lock);
283 
284 	return ret ? ret : len;
285 }
286 
287 static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9910_set_parameter, 0);
288 
ad9910_init(struct ad9910_state * st)289 static void ad9910_init(struct ad9910_state *st)
290 {
291 	struct spi_message msg;
292 	struct spi_transfer xfer;
293 	int ret;
294 	u8 cfr[5];
295 
296 	cfr[0] = CFR1;
297 	cfr[1] = 0;
298 	cfr[2] = MANUAL_OSK | INVSIC | DDS_SINEOP;
299 	cfr[3] = AUTO_OSK | OSKEN | ACLR_PHA | ACLR_DIG | LOAD_LRR;
300 	cfr[4] = 0;
301 
302 	mutex_lock(&st->lock);
303 
304 	xfer.len = 5;
305 	xfer.tx_buf = &cfr;
306 
307 	spi_message_init(&msg);
308 	spi_message_add_tail(&xfer, &msg);
309 	ret = spi_sync(st->sdev, &msg);
310 	if (ret)
311 		goto error_ret;
312 
313 	cfr[0] = CFR2;
314 	cfr[1] = ENA_AMP;
315 	cfr[2] = READ_FTW | DIGR_ENA | ITER_IOUPD;
316 	cfr[3] = TX_ENA | PDCLK_INV | PDCLK_ENB;
317 	cfr[4] = PARA_ENA;
318 
319 	xfer.len = 5;
320 	xfer.tx_buf = &cfr;
321 
322 	spi_message_init(&msg);
323 	spi_message_add_tail(&xfer, &msg);
324 	ret = spi_sync(st->sdev, &msg);
325 	if (ret)
326 		goto error_ret;
327 
328 	cfr[0] = CFR3;
329 	cfr[1] = PLL_ENA;
330 	cfr[2] = 0;
331 	cfr[3] = REFCLK_RST | REFCLK_BYP;
332 	cfr[4] = 0;
333 
334 	xfer.len = 5;
335 	xfer.tx_buf = &cfr;
336 
337 	spi_message_init(&msg);
338 	spi_message_add_tail(&xfer, &msg);
339 	ret = spi_sync(st->sdev, &msg);
340 	if (ret)
341 		goto error_ret;
342 
343 error_ret:
344 	mutex_unlock(&st->lock);
345 
346 
347 
348 }
349 
350 static struct attribute *ad9910_attributes[] = {
351 	&iio_dev_attr_dds.dev_attr.attr,
352 	NULL,
353 };
354 
355 static const struct attribute_group ad9910_attribute_group = {
356 	.attrs = ad9910_attributes,
357 };
358 
359 static const struct iio_info ad9910_info = {
360 	.attrs = &ad9910_attribute_group,
361 	.driver_module = THIS_MODULE,
362 };
363 
ad9910_probe(struct spi_device * spi)364 static int __devinit ad9910_probe(struct spi_device *spi)
365 {
366 	struct ad9910_state *st;
367 	struct iio_dev *idev;
368 	int ret = 0;
369 
370 	idev = iio_allocate_device(sizeof(*st));
371 	if (idev == NULL) {
372 		ret = -ENOMEM;
373 		goto error_ret;
374 	}
375 	spi_set_drvdata(spi, idev);
376 	st = iio_priv(idev);
377 	mutex_init(&st->lock);
378 	st->sdev = spi;
379 
380 	idev->dev.parent = &spi->dev;
381 	idev->info = &ad9910_info;
382 	idev->modes = INDIO_DIRECT_MODE;
383 
384 	ret = iio_device_register(idev);
385 	if (ret)
386 		goto error_free_dev;
387 	spi->max_speed_hz = 2000000;
388 	spi->mode = SPI_MODE_3;
389 	spi->bits_per_word = 8;
390 	spi_setup(spi);
391 	ad9910_init(st);
392 	return 0;
393 
394 error_free_dev:
395 	iio_free_device(idev);
396 error_ret:
397 	return ret;
398 }
399 
ad9910_remove(struct spi_device * spi)400 static int __devexit ad9910_remove(struct spi_device *spi)
401 {
402 	iio_device_unregister(spi_get_drvdata(spi));
403 	iio_free_device(spi_get_drvdata(spi));
404 
405 	return 0;
406 }
407 
408 static struct spi_driver ad9910_driver = {
409 	.driver = {
410 		.name = DRV_NAME,
411 		.owner = THIS_MODULE,
412 	},
413 	.probe = ad9910_probe,
414 	.remove = __devexit_p(ad9910_remove),
415 };
416 module_spi_driver(ad9910_driver);
417 
418 MODULE_AUTHOR("Cliff Cai");
419 MODULE_DESCRIPTION("Analog Devices ad9910 driver");
420 MODULE_LICENSE("GPL v2");
421 MODULE_ALIAS("spi:" DRV_NAME);
422