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 = 𝔠 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 = 𝔠 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 = 𝔠 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