12996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai/*
22996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai * Driver for ADI Direct Digital Synthesis ad9910
32996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai *
42996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai * Copyright (c) 2010 Analog Devices Inc.
52996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai *
62996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai * This program is free software; you can redistribute it and/or modify
72996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai * it under the terms of the GNU General Public License version 2 as
82996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai * published by the Free Software Foundation.
92996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai *
102996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai */
112996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#include <linux/types.h>
122996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#include <linux/mutex.h>
132996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#include <linux/device.h>
142996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#include <linux/spi/spi.h>
152996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#include <linux/slab.h>
162996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#include <linux/sysfs.h>
1799c978529a40132a6f7a5f136b4362b56fc88d8cPaul Gortmaker#include <linux/module.h>
182996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
192996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#include "../iio.h"
202996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#include "../sysfs.h"
212996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
222996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define DRV_NAME "ad9910"
232996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
242996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define CFR1 0x0
252996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define CFR2 0x1
262996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define CFR3 0x2
272996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
282996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define AUXDAC 0x3
292996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define IOUPD 0x4
302996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define FTW 0x7
312996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define POW 0x8
322996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define ASF 0x9
332996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define MULTC 0x0A
342996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define DIG_RAMPL 0x0B
352996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define DIG_RAMPS 0x0C
362996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define DIG_RAMPR 0x0D
372996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define SIN_TONEP0 0x0E
382996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define SIN_TONEP1 0x0F
392996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define SIN_TONEP2 0x10
402996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define SIN_TONEP3 0x11
412996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define SIN_TONEP4 0x12
422996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define SIN_TONEP5 0x13
432996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define SIN_TONEP6 0x14
442996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define SIN_TONEP7 0x15
452996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
462996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define RAM_ENABLE	(1 << 7)
472996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
482996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define MANUAL_OSK	(1 << 7)
492996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define INVSIC		(1 << 6)
502996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define DDS_SINEOP	(1)
512996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
522996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define AUTO_OSK	(1)
532996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define OSKEN		(1 << 1)
542996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define LOAD_ARR	(1 << 2)
552996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define CLR_PHA		(1 << 3)
562996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define CLR_DIG		(1 << 4)
572996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define ACLR_PHA	(1 << 5)
582996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define ACLR_DIG	(1 << 6)
592996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define LOAD_LRR	(1 << 7)
602996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
612996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define LSB_FST		(1)
622996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define SDIO_IPT	(1 << 1)
632996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define EXT_PWD		(1 << 3)
642996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define ADAC_PWD	(1 << 4)
652996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define REFCLK_PWD	(1 << 5)
662996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define DAC_PWD		(1 << 6)
672996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define DIG_PWD		(1 << 7)
682996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
692996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define ENA_AMP		(1)
702996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define READ_FTW	(1)
712996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define DIGR_LOW	(1 << 1)
722996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define DIGR_HIGH	(1 << 2)
732996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define DIGR_ENA	(1 << 3)
742996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define SYNCCLK_ENA	(1 << 6)
752996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define ITER_IOUPD	(1 << 7)
762996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
772996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define TX_ENA		(1 << 1)
782996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define PDCLK_INV	(1 << 2)
792996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define PDCLK_ENB	(1 << 3)
802996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
812996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define PARA_ENA	(1 << 4)
822996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define SYNC_DIS	(1 << 5)
832996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define DATA_ASS	(1 << 6)
842996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define MATCH_ENA	(1 << 7)
852996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
862996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define PLL_ENA		(1)
872996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define PFD_RST		(1 << 2)
882996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define REFCLK_RST	(1 << 6)
892996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai#define REFCLK_BYP	(1 << 7)
902996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
912996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai/* Register format: 1 byte addr + value */
922996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Caistruct ad9910_config {
932996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 auxdac[5];
942996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 ioupd[5];
952996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 ftw[5];
962996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 pow[3];
972996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 asf[5];
982996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 multc[5];
992996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 dig_rampl[9];
1002996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 dig_ramps[9];
1012996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 dig_rampr[5];
1022996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 sin_tonep0[9];
1032996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 sin_tonep1[9];
1042996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 sin_tonep2[9];
1052996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 sin_tonep3[9];
1062996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 sin_tonep4[9];
1072996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 sin_tonep5[9];
1082996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 sin_tonep6[9];
1092996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 sin_tonep7[9];
1102996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai};
1112996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1122996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Caistruct ad9910_state {
1132996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	struct mutex lock;
1142996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	struct spi_device *sdev;
1152996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai};
1162996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1172996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Caistatic ssize_t ad9910_set_parameter(struct device *dev,
1182996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai					struct device_attribute *attr,
1192996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai					const char *buf,
1202996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai					size_t len)
1212996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai{
1222996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	struct spi_message msg;
1232996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	struct spi_transfer xfer;
1242996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	int ret;
1252996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	struct ad9910_config *config = (struct ad9910_config *)buf;
1262996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	struct iio_dev *idev = dev_get_drvdata(dev);
127fb565f132bd43924c053abb8b15e8d6e57606c0cJonathan Cameron	struct ad9910_state *st = iio_priv(idev);
1282996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1292996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 5;
1302996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->auxdac[0];
1312996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	mutex_lock(&st->lock);
1322996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1332996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
1342996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
1352996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
1362996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
1372996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
1382996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1392996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 5;
1402996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->ioupd[0];
1412996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1422996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
1432996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
1442996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
1452996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
1462996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
1472996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1482996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 5;
1492996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->ftw[0];
1502996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1512996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
1522996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
1532996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
1542996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
1552996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
1562996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1572996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 3;
1582996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->pow[0];
1592996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1602996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
1612996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
1622996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
1632996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
1642996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
1652996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1662996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 5;
1672996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->asf[0];
1682996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1692996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
1702996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
1712996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
1722996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
1732996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
1742996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1752996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 5;
1762996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->multc[0];
1772996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1782996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
1792996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
1802996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
1812996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
1822996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
1832996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1842996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 9;
1852996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->dig_rampl[0];
1862996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1872996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
1882996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
1892996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
1902996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
1912996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
1922996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1932996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 9;
1942996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->dig_ramps[0];
1952996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
1962996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
1972996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
1982996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
1992996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
2002996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
2012996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
2022996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 5;
2032996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->dig_rampr[0];
2042996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
2052996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
2062996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
2072996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
2082996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
2092996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
2102996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
2112996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 9;
2122996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->sin_tonep0[0];
2132996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
2142996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
2152996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
2162996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
2172996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
2182996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
21959a126418b96e9f5337d431e6024a8d50bbd6e4eDan Carpenter
2202996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 9;
2212996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->sin_tonep1[0];
2222996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
2232996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
2242996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
2252996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
2262996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
2272996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
22859a126418b96e9f5337d431e6024a8d50bbd6e4eDan Carpenter
2292996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 9;
2302996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->sin_tonep2[0];
2312996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
2322996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
2332996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
2342996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
2352996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
2362996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
2372996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 9;
2382996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->sin_tonep3[0];
2392996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
2402996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
2412996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
2422996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
2432996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
2442996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
24559a126418b96e9f5337d431e6024a8d50bbd6e4eDan Carpenter
2462996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 9;
2472996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->sin_tonep4[0];
2482996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
2492996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
2502996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
2512996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
2522996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
2532996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
25459a126418b96e9f5337d431e6024a8d50bbd6e4eDan Carpenter
2552996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 9;
2562996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->sin_tonep5[0];
2572996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
2582996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
2592996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
2602996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
2612996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
2622996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
26359a126418b96e9f5337d431e6024a8d50bbd6e4eDan Carpenter
2642996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 9;
2652996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->sin_tonep6[0];
2662996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
2672996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
2682996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
2692996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
2702996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
2712996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
27259a126418b96e9f5337d431e6024a8d50bbd6e4eDan Carpenter
2732996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 9;
2742996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &config->sin_tonep7[0];
2752996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
2762996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
2772996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
2782996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
2792996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
2802996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
2812996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Caierror_ret:
2822996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	mutex_unlock(&st->lock);
2832996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
2842996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	return ret ? ret : len;
2852996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai}
2862996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
2872996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Caistatic IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9910_set_parameter, 0);
2882996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
2892996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Caistatic void ad9910_init(struct ad9910_state *st)
2902996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai{
2912996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	struct spi_message msg;
2922996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	struct spi_transfer xfer;
2932996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	int ret;
2942996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	u8 cfr[5];
2952996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
2962996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	cfr[0] = CFR1;
2972996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	cfr[1] = 0;
2982996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	cfr[2] = MANUAL_OSK | INVSIC | DDS_SINEOP;
2992996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	cfr[3] = AUTO_OSK | OSKEN | ACLR_PHA | ACLR_DIG | LOAD_LRR;
3002996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	cfr[4] = 0;
3012996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3022996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	mutex_lock(&st->lock);
3032996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3042996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 5;
3052996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &cfr;
3062996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3072996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
3082996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
3092996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
3102996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
3112996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
3122996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3132996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	cfr[0] = CFR2;
3142996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	cfr[1] = ENA_AMP;
3152996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	cfr[2] = READ_FTW | DIGR_ENA | ITER_IOUPD;
3162996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	cfr[3] = TX_ENA | PDCLK_INV | PDCLK_ENB;
3172996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	cfr[4] = PARA_ENA;
3182996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3192996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 5;
3202996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &cfr;
3212996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3222996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
3232996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
3242996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
3252996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
3262996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
3272996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3282996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	cfr[0] = CFR3;
3292996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	cfr[1] = PLL_ENA;
3302996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	cfr[2] = 0;
3312996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	cfr[3] = REFCLK_RST | REFCLK_BYP;
3322996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	cfr[4] = 0;
3332996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3342996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.len = 5;
3352996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	xfer.tx_buf = &cfr;
3362996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3372996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_init(&msg);
3382996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_message_add_tail(&xfer, &msg);
3392996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ret = spi_sync(st->sdev, &msg);
3402996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
3412996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
3422996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3432996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Caierror_ret:
3442996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	mutex_unlock(&st->lock);
3452996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3462996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3472996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3482996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai}
3492996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3502996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Caistatic struct attribute *ad9910_attributes[] = {
3512996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	&iio_dev_attr_dds.dev_attr.attr,
3522996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	NULL,
3532996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai};
3542996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3552996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Caistatic const struct attribute_group ad9910_attribute_group = {
3562996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	.attrs = ad9910_attributes,
3572996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai};
3582996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3596fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameronstatic const struct iio_info ad9910_info = {
3606fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.attrs = &ad9910_attribute_group,
3616fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.driver_module = THIS_MODULE,
3626fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron};
3636fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron
3642996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Caistatic int __devinit ad9910_probe(struct spi_device *spi)
3652996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai{
3662996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	struct ad9910_state *st;
367fb565f132bd43924c053abb8b15e8d6e57606c0cJonathan Cameron	struct iio_dev *idev;
3682996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	int ret = 0;
3692996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
370fb565f132bd43924c053abb8b15e8d6e57606c0cJonathan Cameron	idev = iio_allocate_device(sizeof(*st));
371fb565f132bd43924c053abb8b15e8d6e57606c0cJonathan Cameron	if (idev == NULL) {
3722996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		ret = -ENOMEM;
3732996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_ret;
3742996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	}
375fb565f132bd43924c053abb8b15e8d6e57606c0cJonathan Cameron	spi_set_drvdata(spi, idev);
376fb565f132bd43924c053abb8b15e8d6e57606c0cJonathan Cameron	st = iio_priv(idev);
3772996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	mutex_init(&st->lock);
3782996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	st->sdev = spi;
3792996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
380fb565f132bd43924c053abb8b15e8d6e57606c0cJonathan Cameron	idev->dev.parent = &spi->dev;
381fb565f132bd43924c053abb8b15e8d6e57606c0cJonathan Cameron	idev->info = &ad9910_info;
382fb565f132bd43924c053abb8b15e8d6e57606c0cJonathan Cameron	idev->modes = INDIO_DIRECT_MODE;
3832996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
384fb565f132bd43924c053abb8b15e8d6e57606c0cJonathan Cameron	ret = iio_device_register(idev);
3852996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	if (ret)
3862996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		goto error_free_dev;
3872996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi->max_speed_hz = 2000000;
3882996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi->mode = SPI_MODE_3;
3892996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi->bits_per_word = 8;
3902996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	spi_setup(spi);
3912996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	ad9910_init(st);
3922996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	return 0;
3932996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
3942996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Caierror_free_dev:
395fb565f132bd43924c053abb8b15e8d6e57606c0cJonathan Cameron	iio_free_device(idev);
3962996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Caierror_ret:
3972996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	return ret;
3982996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai}
3992996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
4002996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Caistatic int __devexit ad9910_remove(struct spi_device *spi)
4012996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai{
402fb565f132bd43924c053abb8b15e8d6e57606c0cJonathan Cameron	iio_device_unregister(spi_get_drvdata(spi));
403d2fffd6c2fd60fe9ab63ef30758d9d43a5057549Jonathan Cameron	iio_free_device(spi_get_drvdata(spi));
4042996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
4052996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	return 0;
4062996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai}
4072996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
4082996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Caistatic struct spi_driver ad9910_driver = {
4092996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	.driver = {
4102996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		.name = DRV_NAME,
4112996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai		.owner = THIS_MODULE,
4122996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	},
4132996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	.probe = ad9910_probe,
4142996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai	.remove = __devexit_p(ad9910_remove),
4152996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai};
416ae6ae6fec3f7d6919e0146996df37b665c75f662Lars-Peter Clausenmodule_spi_driver(ad9910_driver);
4172996a2dc38c58f96432a28fdd7f81ccfd692637dCliff Cai
4182996a2dc38c58f96432a28fdd7f81ccfd692637dCliff CaiMODULE_AUTHOR("Cliff Cai");
4192996a2dc38c58f96432a28fdd7f81ccfd692637dCliff CaiMODULE_DESCRIPTION("Analog Devices ad9910 driver");
4202996a2dc38c58f96432a28fdd7f81ccfd692637dCliff CaiMODULE_LICENSE("GPL v2");
42155e4390cb04e8b0fbae8983c3494c9e24132db1bLars-Peter ClausenMODULE_ALIAS("spi:" DRV_NAME);
422