aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/iio/meter/ade7854-spi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-10 19:04:53 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-10 19:04:53 -0500
commit949f6711b83d2809d1ccb9d830155a65fdacdff9 (patch)
tree4b8bdb0e98489bc8ad77fa144926931c37e2e4f2 /drivers/staging/iio/meter/ade7854-spi.c
parent443e6221e465efa8efb752a8405a759ef1161af9 (diff)
parent7959d55679e4360205c9ebc89d40a5503c53bae2 (diff)
Merge branch 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
* 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6: (510 commits) staging: speakup: fix failure handling staging: usbip: remove double giveback of URB Staging: batman-adv: Remove batman-adv from staging Staging: hv: Use only one txf buffer per channel and kmalloc/GFP_KERNEL on initialize staging: hv: remove unneeded osd_schedule_callback staging: hv: convert channel_mgmt.c to not call osd_schedule_callback staging: hv: convert vmbus_on_msg_dpc to not call osd_schedule_callback staging: brcm80211: Fix WL_<type> logging macros Staging: IIO: DDS: AD9833 / AD9834 driver Staging: IIO: dds.h convenience macros Staging: IIO: Direct digital synthesis abi documentation staging: brcm80211: Convert ETHER_TYPE_802_1X to ETH_P_PAE staging: brcm80211: Remove unused ETHER_TYPE_<foo> #defines staging: brcm80211: Remove ETHER_HDR_LEN, use ETH_HLEN staging: brcm80211: Convert ETHER_ADDR_LEN to ETH_ALEN staging: brcm80211: Convert ETHER_IS<FOO> to is_<foo>_ether_addr staging: brcm80211: Remove unused ether_<foo> #defines and struct staging: brcm80211: Convert ETHER_IS_MULTI to is_multicast_ether_addr staging: brcm80211: Remove unused #defines ETHER_<foo>_LOCALADDR Staging: comedi: Fix checkpatch.pl issues in file s526.c ... Fix up trivial conflict in drivers/video/udlfb.c
Diffstat (limited to 'drivers/staging/iio/meter/ade7854-spi.c')
-rw-r--r--drivers/staging/iio/meter/ade7854-spi.c360
1 files changed, 360 insertions, 0 deletions
diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c
new file mode 100644
index 00000000000..fe58103ed4c
--- /dev/null
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -0,0 +1,360 @@
1/*
2 * ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver (SPI Bus)
3 *
4 * Copyright 2010 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/device.h>
10#include <linux/kernel.h>
11#include <linux/spi/spi.h>
12#include <linux/slab.h>
13
14#include "../iio.h"
15#include "ade7854.h"
16
17static int ade7854_spi_write_reg_8(struct device *dev,
18 u16 reg_address,
19 u8 value)
20{
21 int ret;
22 struct spi_message msg;
23 struct iio_dev *indio_dev = dev_get_drvdata(dev);
24 struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
25 struct spi_transfer xfers[] = {
26 {
27 .tx_buf = st->tx,
28 .bits_per_word = 8,
29 .len = 4,
30 }
31 };
32
33 mutex_lock(&st->buf_lock);
34 st->tx[0] = ADE7854_WRITE_REG;
35 st->tx[1] = (reg_address >> 8) & 0xFF;
36 st->tx[2] = reg_address & 0xFF;
37 st->tx[3] = value & 0xFF;
38
39 spi_message_init(&msg);
40 spi_message_add_tail(xfers, &msg);
41 ret = spi_sync(st->spi, &msg);
42 mutex_unlock(&st->buf_lock);
43
44 return ret;
45}
46
47static int ade7854_spi_write_reg_16(struct device *dev,
48 u16 reg_address,
49 u16 value)
50{
51 int ret;
52 struct spi_message msg;
53 struct iio_dev *indio_dev = dev_get_drvdata(dev);
54 struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
55 struct spi_transfer xfers[] = {
56 {
57 .tx_buf = st->tx,
58 .bits_per_word = 8,
59 .len = 5,
60 }
61 };
62
63 mutex_lock(&st->buf_lock);
64 st->tx[0] = ADE7854_WRITE_REG;
65 st->tx[1] = (reg_address >> 8) & 0xFF;
66 st->tx[2] = reg_address & 0xFF;
67 st->tx[3] = (value >> 8) & 0xFF;
68 st->tx[4] = value & 0xFF;
69
70 spi_message_init(&msg);
71 spi_message_add_tail(xfers, &msg);
72 ret = spi_sync(st->spi, &msg);
73 mutex_unlock(&st->buf_lock);
74
75 return ret;
76}
77
78static int ade7854_spi_write_reg_24(struct device *dev,
79 u16 reg_address,
80 u32 value)
81{
82 int ret;
83 struct spi_message msg;
84 struct iio_dev *indio_dev = dev_get_drvdata(dev);
85 struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
86 struct spi_transfer xfers[] = {
87 {
88 .tx_buf = st->tx,
89 .bits_per_word = 8,
90 .len = 6,
91 }
92 };
93
94 mutex_lock(&st->buf_lock);
95 st->tx[0] = ADE7854_WRITE_REG;
96 st->tx[1] = (reg_address >> 8) & 0xFF;
97 st->tx[2] = reg_address & 0xFF;
98 st->tx[3] = (value >> 16) & 0xFF;
99 st->tx[4] = (value >> 8) & 0xFF;
100 st->tx[5] = value & 0xFF;
101
102 spi_message_init(&msg);
103 spi_message_add_tail(xfers, &msg);
104 ret = spi_sync(st->spi, &msg);
105 mutex_unlock(&st->buf_lock);
106
107 return ret;
108}
109
110static int ade7854_spi_write_reg_32(struct device *dev,
111 u16 reg_address,
112 u32 value)
113{
114 int ret;
115 struct spi_message msg;
116 struct iio_dev *indio_dev = dev_get_drvdata(dev);
117 struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
118 struct spi_transfer xfers[] = {
119 {
120 .tx_buf = st->tx,
121 .bits_per_word = 8,
122 .len = 7,
123 }
124 };
125
126 mutex_lock(&st->buf_lock);
127 st->tx[0] = ADE7854_WRITE_REG;
128 st->tx[1] = (reg_address >> 8) & 0xFF;
129 st->tx[2] = reg_address & 0xFF;
130 st->tx[3] = (value >> 24) & 0xFF;
131 st->tx[4] = (value >> 16) & 0xFF;
132 st->tx[5] = (value >> 8) & 0xFF;
133 st->tx[6] = value & 0xFF;
134
135 spi_message_init(&msg);
136 spi_message_add_tail(xfers, &msg);
137 ret = spi_sync(st->spi, &msg);
138 mutex_unlock(&st->buf_lock);
139
140 return ret;
141}
142
143static int ade7854_spi_read_reg_8(struct device *dev,
144 u16 reg_address,
145 u8 *val)
146{
147 struct spi_message msg;
148 struct iio_dev *indio_dev = dev_get_drvdata(dev);
149 struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
150 int ret;
151 struct spi_transfer xfers[] = {
152 {
153 .tx_buf = st->tx,
154 .bits_per_word = 8,
155 .len = 4,
156 },
157 };
158
159 mutex_lock(&st->buf_lock);
160
161 st->tx[0] = ADE7854_READ_REG;
162 st->tx[1] = (reg_address >> 8) & 0xFF;
163 st->tx[2] = reg_address & 0xFF;
164 st->tx[3] = 0;
165
166 spi_message_init(&msg);
167 spi_message_add_tail(xfers, &msg);
168 ret = spi_sync(st->spi, &msg);
169 if (ret) {
170 dev_err(&st->spi->dev, "problem when reading 8 bit register 0x%02X",
171 reg_address);
172 goto error_ret;
173 }
174 *val = st->rx[3];
175
176error_ret:
177 mutex_unlock(&st->buf_lock);
178 return ret;
179}
180
181static int ade7854_spi_read_reg_16(struct device *dev,
182 u16 reg_address,
183 u16 *val)
184{
185 struct spi_message msg;
186 struct iio_dev *indio_dev = dev_get_drvdata(dev);
187 struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
188 int ret;
189 struct spi_transfer xfers[] = {
190 {
191 .tx_buf = st->tx,
192 .bits_per_word = 8,
193 .len = 5,
194 },
195 };
196
197 mutex_lock(&st->buf_lock);
198 st->tx[0] = ADE7854_READ_REG;
199 st->tx[1] = (reg_address >> 8) & 0xFF;
200 st->tx[2] = reg_address & 0xFF;
201 st->tx[3] = 0;
202 st->tx[4] = 0;
203
204 spi_message_init(&msg);
205 spi_message_add_tail(xfers, &msg);
206 ret = spi_sync(st->spi, &msg);
207 if (ret) {
208 dev_err(&st->spi->dev, "problem when reading 16 bit register 0x%02X",
209 reg_address);
210 goto error_ret;
211 }
212 *val = (st->rx[3] << 8) | st->rx[4];
213
214error_ret:
215 mutex_unlock(&st->buf_lock);
216 return ret;
217}
218
219static int ade7854_spi_read_reg_24(struct device *dev,
220 u16 reg_address,
221 u32 *val)
222{
223 struct spi_message msg;
224 struct iio_dev *indio_dev = dev_get_drvdata(dev);
225 struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
226 int ret;
227 struct spi_transfer xfers[] = {
228 {
229 .tx_buf = st->tx,
230 .bits_per_word = 8,
231 .len = 6,
232 },
233 };
234
235 mutex_lock(&st->buf_lock);
236
237 st->tx[0] = ADE7854_READ_REG;
238 st->tx[1] = (reg_address >> 8) & 0xFF;
239 st->tx[2] = reg_address & 0xFF;
240 st->tx[3] = 0;
241 st->tx[4] = 0;
242 st->tx[5] = 0;
243
244 spi_message_init(&msg);
245 spi_message_add_tail(xfers, &msg);
246 ret = spi_sync(st->spi, &msg);
247 if (ret) {
248 dev_err(&st->spi->dev, "problem when reading 24 bit register 0x%02X",
249 reg_address);
250 goto error_ret;
251 }
252 *val = (st->rx[3] << 16) | (st->rx[4] << 8) | st->rx[5];
253
254error_ret:
255 mutex_unlock(&st->buf_lock);
256 return ret;
257}
258
259static int ade7854_spi_read_reg_32(struct device *dev,
260 u16 reg_address,
261 u32 *val)
262{
263 struct spi_message msg;
264 struct iio_dev *indio_dev = dev_get_drvdata(dev);
265 struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
266 int ret;
267 struct spi_transfer xfers[] = {
268 {
269 .tx_buf = st->tx,
270 .bits_per_word = 8,
271 .len = 7,
272 },
273 };
274
275 mutex_lock(&st->buf_lock);
276
277 st->tx[0] = ADE7854_READ_REG;
278 st->tx[1] = (reg_address >> 8) & 0xFF;
279 st->tx[2] = reg_address & 0xFF;
280 st->tx[3] = 0;
281 st->tx[4] = 0;
282 st->tx[5] = 0;
283 st->tx[6] = 0;
284
285 spi_message_init(&msg);
286 spi_message_add_tail(xfers, &msg);
287 ret = spi_sync(st->spi, &msg);
288 if (ret) {
289 dev_err(&st->spi->dev, "problem when reading 32 bit register 0x%02X",
290 reg_address);
291 goto error_ret;
292 }
293 *val = (st->rx[3] << 24) | (st->rx[4] << 16) | (st->rx[5] << 8) | st->rx[6];
294
295error_ret:
296 mutex_unlock(&st->buf_lock);
297 return ret;
298}
299
300static int __devinit ade7854_spi_probe(struct spi_device *spi)
301{
302 int ret;
303 struct ade7854_state *st = kzalloc(sizeof *st, GFP_KERNEL);
304 if (!st) {
305 ret = -ENOMEM;
306 return ret;
307 }
308
309 spi_set_drvdata(spi, st);
310 st->read_reg_8 = ade7854_spi_read_reg_8;
311 st->read_reg_16 = ade7854_spi_read_reg_16;
312 st->read_reg_24 = ade7854_spi_read_reg_24;
313 st->read_reg_32 = ade7854_spi_read_reg_32;
314 st->write_reg_8 = ade7854_spi_write_reg_8;
315 st->write_reg_16 = ade7854_spi_write_reg_16;
316 st->write_reg_24 = ade7854_spi_write_reg_24;
317 st->write_reg_32 = ade7854_spi_write_reg_32;
318 st->irq = spi->irq;
319 st->spi = spi;
320
321 ret = ade7854_probe(st, &spi->dev);
322 if (ret) {
323 kfree(st);
324 return ret;
325 }
326
327 return 0;
328}
329
330static int ade7854_spi_remove(struct spi_device *spi)
331{
332 ade7854_remove(spi_get_drvdata(spi));
333
334 return 0;
335}
336
337static struct spi_driver ade7854_driver = {
338 .driver = {
339 .name = "ade7854",
340 .owner = THIS_MODULE,
341 },
342 .probe = ade7854_spi_probe,
343 .remove = __devexit_p(ade7854_spi_remove),
344};
345
346static __init int ade7854_init(void)
347{
348 return spi_register_driver(&ade7854_driver);
349}
350module_init(ade7854_init);
351
352static __exit void ade7854_exit(void)
353{
354 spi_unregister_driver(&ade7854_driver);
355}
356module_exit(ade7854_exit);
357
358MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
359MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC SPI Driver");
360MODULE_LICENSE("GPL v2");