ad9852.c revision a886689f6c36ccad01d9600a92029f80a2a6279f
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>
17a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
18a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#include "../iio.h"
19a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#include "../sysfs.h"
20a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
21a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define DRV_NAME "ad9852"
22a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
23a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_phaad1 0x0
24a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_phaad2 0x1
25a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_fretu1 0x2
26a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_fretu2 0x3
27a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_delfre 0x4
28a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_updclk 0x5
29a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_ramclk 0x6
30a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_contrl 0x7
31a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_optskm 0x8
32a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_optskr 0xa
33a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define addr_dacctl 0xb
34a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
35a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define COMPPD		(1 << 4)
36a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define REFMULT2	(1 << 2)
37a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define BYPPLL		(1 << 5)
38a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define PLLRANG		(1 << 6)
39a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define IEUPCLK		(1)
40a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define OSKEN		(1 << 5)
41a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
42a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai#define read_bit	(1 << 7)
43a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
44a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai/* Register format: 1 byte addr + value */
45a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistruct ad9852_config {
46a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 phajst0[3];
47a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 phajst1[3];
48a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 fretun1[6];
49a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 fretun2[6];
50a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 dltafre[6];
51a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 updtclk[5];
52a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 ramprat[4];
53a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 control[5];
54a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 outpskm[3];
55a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 outpskr[2];
56a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 daccntl[3];
57a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai};
58a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
59a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistruct ad9852_state {
60a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct mutex lock;
61a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct iio_dev *idev;
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);
75a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct ad9852_state *st = idev->dev_data;
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	mutex_lock(&st->lock);
90a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
91a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
92a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
93a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
94a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
95a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
96a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
97a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 6;
98a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->fretun1[0];
99a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_lock(&st->lock);
100a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
101a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
102a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
103a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
104a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
105a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
106a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
107a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 6;
108a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->fretun2[0];
109a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_lock(&st->lock);
110a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
111a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
112a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
113a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
114a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
115a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
116a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
117a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 6;
118a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->dltafre[0];
119a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_lock(&st->lock);
120a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
121a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
122a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
123a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
124a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
125a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
126a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
127a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 5;
128a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->updtclk[0];
129a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_lock(&st->lock);
130a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
131a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
132a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
133a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
134a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
135a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
136a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
137a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 4;
138a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->ramprat[0];
139a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_lock(&st->lock);
140a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
141a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
142a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
143a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
144a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
145a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
146a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
147a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 5;
148a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->control[0];
149a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_lock(&st->lock);
150a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
151a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
152a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
153a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
154a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
155a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
156a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
157a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 3;
158a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->outpskm[0];
159a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_lock(&st->lock);
160a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
161a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
162a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
163a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
164a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
165a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
166a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
167a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 2;
168a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->outpskr[0];
169a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_lock(&st->lock);
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 Cai	xfer.len = 3;
177a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config->daccntl[0];
178a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_lock(&st->lock);
179a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
180a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
181a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
182a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
183a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
184a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
185a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caierror_ret:
186a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_unlock(&st->lock);
187a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
188a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	return ret ? ret : len;
189a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai}
190a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
191a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9852_set_parameter, 0);
192a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
193a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic void ad9852_init(struct ad9852_state *st)
194a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai{
195a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct spi_message msg;
196a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct spi_transfer xfer;
197a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	int ret;
198a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	u8 config[5];
199a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
200a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	config[0] = addr_contrl;
201a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	config[1] = COMPPD;
202a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	config[2] = REFMULT2 | BYPPLL | PLLRANG;
203a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	config[3] = IEUPCLK;
204a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	config[4] = OSKEN;
205a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
206a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_lock(&st->lock);
207a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
208a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.len = 5;
209a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	xfer.tx_buf = &config;
210a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
211a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_init(&msg);
212a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_message_add_tail(&xfer, &msg);
213a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = spi_sync(st->sdev, &msg);
214a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
215a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
216a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
217a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caierror_ret:
218a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_unlock(&st->lock);
219a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
220a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
221a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
222a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai}
223a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
224a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic struct attribute *ad9852_attributes[] = {
225a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	&iio_dev_attr_dds.dev_attr.attr,
226a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	NULL,
227a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai};
228a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
229a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic const struct attribute_group ad9852_attribute_group = {
230a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	.name = DRV_NAME,
231a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	.attrs = ad9852_attributes,
232a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai};
233a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
234a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic int __devinit ad9852_probe(struct spi_device *spi)
235a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai{
236a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct ad9852_state *st;
237a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	int ret = 0;
238a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
239a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	st = kzalloc(sizeof(*st), GFP_KERNEL);
240a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (st == NULL) {
241a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		ret = -ENOMEM;
242a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_ret;
243a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	}
244a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_set_drvdata(spi, st);
245a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
246a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	mutex_init(&st->lock);
247a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	st->sdev = spi;
248a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
249a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	st->idev = iio_allocate_device();
250a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (st->idev == NULL) {
251a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		ret = -ENOMEM;
252a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_free_st;
253a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	}
254a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	st->idev->dev.parent = &spi->dev;
255a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	st->idev->num_interrupt_lines = 0;
256a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	st->idev->event_attrs = NULL;
257a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
258a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	st->idev->attrs = &ad9852_attribute_group;
259a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	st->idev->dev_data = (void *)(st);
260a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	st->idev->driver_module = THIS_MODULE;
261a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	st->idev->modes = INDIO_DIRECT_MODE;
262a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
263a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ret = iio_device_register(st->idev);
264a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	if (ret)
265a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		goto error_free_dev;
266a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi->max_speed_hz = 2000000;
267a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi->mode = SPI_MODE_3;
268a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi->bits_per_word = 8;
269a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_setup(spi);
270a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	ad9852_init(st);
271a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	return 0;
272a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
273a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caierror_free_dev:
274a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	iio_free_device(st->idev);
275a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caierror_free_st:
276a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	kfree(st);
277a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caierror_ret:
278a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	return ret;
279a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai}
280a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
281a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic int __devexit ad9852_remove(struct spi_device *spi)
282a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai{
283a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	struct ad9852_state *st = spi_get_drvdata(spi);
284a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
285a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	iio_device_unregister(st->idev);
286a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	kfree(st);
287a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
288a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	return 0;
289a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai}
290a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
291a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic struct spi_driver ad9852_driver = {
292a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	.driver = {
293a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		.name = DRV_NAME,
294a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai		.owner = THIS_MODULE,
295a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	},
296a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	.probe = ad9852_probe,
297a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	.remove = __devexit_p(ad9852_remove),
298a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai};
299a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
300a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic __init int ad9852_spi_init(void)
301a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai{
302a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	return spi_register_driver(&ad9852_driver);
303a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai}
304a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caimodule_init(ad9852_spi_init);
305a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
306a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caistatic __exit void ad9852_spi_exit(void)
307a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai{
308a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai	spi_unregister_driver(&ad9852_driver);
309a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai}
310a886689f6c36ccad01d9600a92029f80a2a6279fCliff Caimodule_exit(ad9852_spi_exit);
311a886689f6c36ccad01d9600a92029f80a2a6279fCliff Cai
312a886689f6c36ccad01d9600a92029f80a2a6279fCliff CaiMODULE_AUTHOR("Cliff Cai");
313a886689f6c36ccad01d9600a92029f80a2a6279fCliff CaiMODULE_DESCRIPTION("Analog Devices ad9852 driver");
314a886689f6c36ccad01d9600a92029f80a2a6279fCliff CaiMODULE_LICENSE("GPL v2");
315