1a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai/*
2a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai * Driver for ADI Direct Digital Synthesis ad9852
3a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai *
4a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai * Copyright (c) 2010 Analog Devices Inc.
5a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai *
6a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai * This program is free software; you can redistribute it and/or modify
7a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai * it under the terms of the GNU General Public License version 2 as
8a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai * published by the Free Software Foundation.
9a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai *
10a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai */
11a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#include <linux/types.h>
12a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#include <linux/mutex.h>
13a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#include <linux/device.h>
14a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#include <linux/spi/spi.h>
15a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#include <linux/slab.h>
16a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#include <linux/sysfs.h>
1799c978529a40132a6f7a5f136b4362b56fc88d8cPaul Gortmaker#include <linux/module.h>
18a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
19a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#include "../iio.h"
20a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#include "../sysfs.h"
21a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
22a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define DRV_NAME "ad9852"
23a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
24a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_phaad1 0x0
25a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_phaad2 0x1
26a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_fretu1 0x2
27a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_fretu2 0x3
28a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_delfre 0x4
29a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_updclk 0x5
30a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_ramclk 0x6
31a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_contrl 0x7
32a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_optskm 0x8
33a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_optskr 0xa
34a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_dacctl 0xb
35a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
36a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define COMPPD		(1 << 4)
37a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define REFMULT2	(1 << 2)
38a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define BYPPLL		(1 << 5)
39a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define PLLRANG		(1 << 6)
40a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define IEUPCLK		(1)
41a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define OSKEN		(1 << 5)
42a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
43a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define read_bit	(1 << 7)
44a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
45a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai/* Register format: 1 byte addr + value */
46a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistruct ad9852_config {
47a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 phajst0[3];
48a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 phajst1[3];
49a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 fretun1[6];
50a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 fretun2[6];
51a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 dltafre[6];
52a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 updtclk[5];
53a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 ramprat[4];
54a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 control[5];
55a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 outpskm[3];
56a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 outpskr[2];
57a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 daccntl[3];
58a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai};
59a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
60a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistruct ad9852_state {
61a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct mutex lock;
62a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct spi_device *sdev;
63a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai};
64a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
65a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic ssize_t ad9852_set_parameter(struct device *dev,
66a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai					struct device_attribute *attr,
67a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai					const char *buf,
68a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai					size_t len)
69a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai{
70a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct spi_message msg;
71a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct spi_transfer xfer;
72a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	int ret;
73a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct ad9852_config *config = (struct ad9852_config *)buf;
74a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct iio_dev *idev = dev_get_drvdata(dev);
75a28299114b2035ef4cf356c590ab946b73a9268eJonathan Cameron	struct ad9852_state *st = iio_priv(idev);
76a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
77a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 3;
78a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->phajst0[0];
79a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_lock(&st->lock);
80a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
81a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
82a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
83a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
84a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
85a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
86a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
87a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 3;
88a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->phajst1[0];
89a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
90a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
91a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
92a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
93a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
94a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
95a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
96a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 6;
97a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->fretun1[0];
98a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
99a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
100a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
101a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
102a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
103a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
104a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
105a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 6;
106a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->fretun2[0];
107a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
108a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
109a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
110a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
111a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
112a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
113a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
114a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 6;
115a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->dltafre[0];
116a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
117a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
118a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
119a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
120a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
121a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
122a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
123a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 5;
124a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->updtclk[0];
125a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
126a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
127a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
128a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
129a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
130a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
131a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
132a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 4;
133a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->ramprat[0];
134a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
135a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
136a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
137a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
138a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
139a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
140a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
141a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 5;
142a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->control[0];
143a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
144a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
145a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
146a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
147a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
148a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
149a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
150a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 3;
151a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->outpskm[0];
152a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
153a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
154a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
155a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
156a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
157a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
158a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
159a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 2;
160a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->outpskr[0];
161a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
162a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
163a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
164a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
165a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
166a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
16759a126418b96e9f5337d431e6024a8d50bbd6e4eDan Carpenter
168a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 3;
169a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->daccntl[0];
170a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
171a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
172a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
173a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
174a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
175a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
176a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caierror_ret:
177a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_unlock(&st->lock);
178a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
179a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	return ret ? ret : len;
180a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai}
181a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
182a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9852_set_parameter, 0);
183a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
184a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic void ad9852_init(struct ad9852_state *st)
185a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai{
186a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct spi_message msg;
187a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct spi_transfer xfer;
188a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	int ret;
189a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 config[5];
190a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
191a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	config[0] = addr_contrl;
192a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	config[1] = COMPPD;
193a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	config[2] = REFMULT2 | BYPPLL | PLLRANG;
194a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	config[3] = IEUPCLK;
195a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	config[4] = OSKEN;
196a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
197a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_lock(&st->lock);
198a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
199a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 5;
200a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config;
201a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
202a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
203a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
204a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
205a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
206a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
207a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
208a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caierror_ret:
209a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_unlock(&st->lock);
210a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
211a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
212a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
213a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai}
214a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
215a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic struct attribute *ad9852_attributes[] = {
216a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	&iio_dev_attr_dds.dev_attr.attr,
217a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	NULL,
218a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai};
219a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
220a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic const struct attribute_group ad9852_attribute_group = {
221a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	.attrs = ad9852_attributes,
222a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai};
223a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
2246fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameronstatic const struct iio_info ad9852_info = {
2256fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.attrs = &ad9852_attribute_group,
2266fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.driver_module = THIS_MODULE,
2276fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron};
2286fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron
229a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic int __devinit ad9852_probe(struct spi_device *spi)
230a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai{
231a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct ad9852_state *st;
232a28299114b2035ef4cf356c590ab946b73a9268eJonathan Cameron	struct iio_dev *idev;
233a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	int ret = 0;
234a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
235a28299114b2035ef4cf356c590ab946b73a9268eJonathan Cameron	idev = iio_allocate_device(sizeof(*st));
236a28299114b2035ef4cf356c590ab946b73a9268eJonathan Cameron	if (idev == NULL) {
237a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		ret = -ENOMEM;
238a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
239a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	}
240a28299114b2035ef4cf356c590ab946b73a9268eJonathan Cameron	st = iio_priv(idev);
241a28299114b2035ef4cf356c590ab946b73a9268eJonathan Cameron	spi_set_drvdata(spi, idev);
242a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_init(&st->lock);
243a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	st->sdev = spi;
244a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
245a28299114b2035ef4cf356c590ab946b73a9268eJonathan Cameron	idev->dev.parent = &spi->dev;
246a28299114b2035ef4cf356c590ab946b73a9268eJonathan Cameron	idev->info = &ad9852_info;
247a28299114b2035ef4cf356c590ab946b73a9268eJonathan Cameron	idev->modes = INDIO_DIRECT_MODE;
248a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
249a28299114b2035ef4cf356c590ab946b73a9268eJonathan Cameron	ret = iio_device_register(idev);
250a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
251a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_free_dev;
252a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi->max_speed_hz = 2000000;
253a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi->mode = SPI_MODE_3;
254a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi->bits_per_word = 8;
255a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_setup(spi);
256a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ad9852_init(st);
257a28299114b2035ef4cf356c590ab946b73a9268eJonathan Cameron
258a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	return 0;
259a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
260a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caierror_free_dev:
261a28299114b2035ef4cf356c590ab946b73a9268eJonathan Cameron	iio_free_device(idev);
262a28299114b2035ef4cf356c590ab946b73a9268eJonathan Cameron
263a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caierror_ret:
264a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	return ret;
265a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai}
266a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
267a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic int __devexit ad9852_remove(struct spi_device *spi)
268a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai{
269a28299114b2035ef4cf356c590ab946b73a9268eJonathan Cameron	iio_device_unregister(spi_get_drvdata(spi));
270d2fffd6c2fd60fe9ab63ef30758d9d43a5057549Jonathan Cameron	iio_free_device(spi_get_drvdata(spi));
271a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
272a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	return 0;
273a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai}
274a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
275a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic struct spi_driver ad9852_driver = {
276a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	.driver = {
277a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		.name = DRV_NAME,
278a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		.owner = THIS_MODULE,
279a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	},
280a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	.probe = ad9852_probe,
281a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	.remove = __devexit_p(ad9852_remove),
282a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai};
283ae6ae6fec3f7d6919e0146996df37b665c75f662Lars-Peter Clausenmodule_spi_driver(ad9852_driver);
284a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
285a886689f6c36ccad01d9600a92029f80a2a6279fCliff CaiMODULE_AUTHOR("Cliff Cai");
286a886689f6c36ccad01d9600a92029f80a2a6279fCliff CaiMODULE_DESCRIPTION("Analog Devices ad9852 driver");
287a886689f6c36ccad01d9600a92029f80a2a6279fCliff CaiMODULE_LICENSE("GPL v2");
28855e4390cb04e8b0fbae8983c3494c9e24132db1bLars-Peter ClausenMODULE_ALIAS("spi:" DRV_NAME);
289