aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/iio/meter/ade7753.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/ade7753.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/ade7753.c')
-rw-r--r--drivers/staging/iio/meter/ade7753.c730
1 files changed, 730 insertions, 0 deletions
diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
new file mode 100644
index 00000000000..e72afbd2b84
--- /dev/null
+++ b/drivers/staging/iio/meter/ade7753.c
@@ -0,0 +1,730 @@
1/*
2 * ADE7753 Single-Phase Multifunction Metering IC with di/dt Sensor Interface Driver
3 *
4 * Copyright 2010 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/interrupt.h>
10#include <linux/irq.h>
11#include <linux/gpio.h>
12#include <linux/delay.h>
13#include <linux/mutex.h>
14#include <linux/device.h>
15#include <linux/kernel.h>
16#include <linux/spi/spi.h>
17#include <linux/slab.h>
18#include <linux/sysfs.h>
19#include <linux/list.h>
20
21#include "../iio.h"
22#include "../sysfs.h"
23#include "meter.h"
24#include "ade7753.h"
25
26int ade7753_spi_write_reg_8(struct device *dev,
27 u8 reg_address,
28 u8 val)
29{
30 int ret;
31 struct iio_dev *indio_dev = dev_get_drvdata(dev);
32 struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
33
34 mutex_lock(&st->buf_lock);
35 st->tx[0] = ADE7753_WRITE_REG(reg_address);
36 st->tx[1] = val;
37
38 ret = spi_write(st->us, st->tx, 2);
39 mutex_unlock(&st->buf_lock);
40
41 return ret;
42}
43
44static int ade7753_spi_write_reg_16(struct device *dev,
45 u8 reg_address,
46 u16 value)
47{
48 int ret;
49 struct spi_message msg;
50 struct iio_dev *indio_dev = dev_get_drvdata(dev);
51 struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
52 struct spi_transfer xfers[] = {
53 {
54 .tx_buf = st->tx,
55 .bits_per_word = 8,
56 .len = 3,
57 }
58 };
59
60 mutex_lock(&st->buf_lock);
61 st->tx[0] = ADE7753_WRITE_REG(reg_address);
62 st->tx[1] = (value >> 8) & 0xFF;
63 st->tx[2] = value & 0xFF;
64
65 spi_message_init(&msg);
66 spi_message_add_tail(xfers, &msg);
67 ret = spi_sync(st->us, &msg);
68 mutex_unlock(&st->buf_lock);
69
70 return ret;
71}
72
73static int ade7753_spi_read_reg_8(struct device *dev,
74 u8 reg_address,
75 u8 *val)
76{
77 struct spi_message msg;
78 struct iio_dev *indio_dev = dev_get_drvdata(dev);
79 struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
80 int ret;
81 struct spi_transfer xfers[] = {
82 {
83 .tx_buf = st->tx,
84 .rx_buf = st->rx,
85 .bits_per_word = 8,
86 .len = 2,
87 },
88 };
89
90 mutex_lock(&st->buf_lock);
91 st->tx[0] = ADE7753_READ_REG(reg_address);
92 st->tx[1] = 0;
93
94 spi_message_init(&msg);
95 spi_message_add_tail(xfers, &msg);
96 ret = spi_sync(st->us, &msg);
97 if (ret) {
98 dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X",
99 reg_address);
100 goto error_ret;
101 }
102 *val = st->rx[1];
103
104error_ret:
105 mutex_unlock(&st->buf_lock);
106 return ret;
107}
108
109static int ade7753_spi_read_reg_16(struct device *dev,
110 u8 reg_address,
111 u16 *val)
112{
113 struct spi_message msg;
114 struct iio_dev *indio_dev = dev_get_drvdata(dev);
115 struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
116 int ret;
117 struct spi_transfer xfers[] = {
118 {
119 .tx_buf = st->tx,
120 .rx_buf = st->rx,
121 .bits_per_word = 8,
122 .len = 3,
123 },
124 };
125
126 mutex_lock(&st->buf_lock);
127 st->tx[0] = ADE7753_READ_REG(reg_address);
128 st->tx[1] = 0;
129 st->tx[2] = 0;
130
131 spi_message_init(&msg);
132 spi_message_add_tail(xfers, &msg);
133 ret = spi_sync(st->us, &msg);
134 if (ret) {
135 dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
136 reg_address);
137 goto error_ret;
138 }
139 *val = (st->rx[1] << 8) | st->rx[2];
140
141error_ret:
142 mutex_unlock(&st->buf_lock);
143 return ret;
144}
145
146static int ade7753_spi_read_reg_24(struct device *dev,
147 u8 reg_address,
148 u32 *val)
149{
150 struct spi_message msg;
151 struct iio_dev *indio_dev = dev_get_drvdata(dev);
152 struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
153 int ret;
154 struct spi_transfer xfers[] = {
155 {
156 .tx_buf = st->tx,
157 .rx_buf = st->rx,
158 .bits_per_word = 8,
159 .len = 4,
160 },
161 };
162
163 mutex_lock(&st->buf_lock);
164 st->tx[0] = ADE7753_READ_REG(reg_address);
165 st->tx[1] = 0;
166 st->tx[2] = 0;
167 st->tx[3] = 0;
168
169 spi_message_init(&msg);
170 spi_message_add_tail(xfers, &msg);
171 ret = spi_sync(st->us, &msg);
172 if (ret) {
173 dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X",
174 reg_address);
175 goto error_ret;
176 }
177 *val = (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3];
178
179error_ret:
180 mutex_unlock(&st->buf_lock);
181 return ret;
182}
183
184static ssize_t ade7753_read_8bit(struct device *dev,
185 struct device_attribute *attr,
186 char *buf)
187{
188 int ret;
189 u8 val = 0;
190 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
191
192 ret = ade7753_spi_read_reg_8(dev, this_attr->address, &val);
193 if (ret)
194 return ret;
195
196 return sprintf(buf, "%u\n", val);
197}
198
199static ssize_t ade7753_read_16bit(struct device *dev,
200 struct device_attribute *attr,
201 char *buf)
202{
203 int ret;
204 u16 val = 0;
205 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
206
207 ret = ade7753_spi_read_reg_16(dev, this_attr->address, &val);
208 if (ret)
209 return ret;
210
211 return sprintf(buf, "%u\n", val);
212}
213
214static ssize_t ade7753_read_24bit(struct device *dev,
215 struct device_attribute *attr,
216 char *buf)
217{
218 int ret;
219 u32 val = 0;
220 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
221
222 ret = ade7753_spi_read_reg_24(dev, this_attr->address, &val);
223 if (ret)
224 return ret;
225
226 return sprintf(buf, "%u\n", val & 0xFFFFFF);
227}
228
229static ssize_t ade7753_write_8bit(struct device *dev,
230 struct device_attribute *attr,
231 const char *buf,
232 size_t len)
233{
234 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
235 int ret;
236 long val;
237
238 ret = strict_strtol(buf, 10, &val);
239 if (ret)
240 goto error_ret;
241 ret = ade7753_spi_write_reg_8(dev, this_attr->address, val);
242
243error_ret:
244 return ret ? ret : len;
245}
246
247static ssize_t ade7753_write_16bit(struct device *dev,
248 struct device_attribute *attr,
249 const char *buf,
250 size_t len)
251{
252 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
253 int ret;
254 long val;
255
256 ret = strict_strtol(buf, 10, &val);
257 if (ret)
258 goto error_ret;
259 ret = ade7753_spi_write_reg_16(dev, this_attr->address, val);
260
261error_ret:
262 return ret ? ret : len;
263}
264
265static int ade7753_reset(struct device *dev)
266{
267 int ret;
268 u16 val;
269 ade7753_spi_read_reg_16(dev,
270 ADE7753_MODE,
271 &val);
272 val |= 1 << 6; /* Software Chip Reset */
273 ret = ade7753_spi_write_reg_16(dev,
274 ADE7753_MODE,
275 val);
276
277 return ret;
278}
279
280static ssize_t ade7753_write_reset(struct device *dev,
281 struct device_attribute *attr,
282 const char *buf, size_t len)
283{
284 if (len < 1)
285 return -1;
286 switch (buf[0]) {
287 case '1':
288 case 'y':
289 case 'Y':
290 return ade7753_reset(dev);
291 }
292 return -1;
293}
294
295static IIO_DEV_ATTR_AENERGY(ade7753_read_24bit, ADE7753_AENERGY);
296static IIO_DEV_ATTR_LAENERGY(ade7753_read_24bit, ADE7753_LAENERGY);
297static IIO_DEV_ATTR_VAENERGY(ade7753_read_24bit, ADE7753_VAENERGY);
298static IIO_DEV_ATTR_LVAENERGY(ade7753_read_24bit, ADE7753_LVAENERGY);
299static IIO_DEV_ATTR_CFDEN(S_IWUSR | S_IRUGO,
300 ade7753_read_16bit,
301 ade7753_write_16bit,
302 ADE7753_CFDEN);
303static IIO_DEV_ATTR_CFNUM(S_IWUSR | S_IRUGO,
304 ade7753_read_8bit,
305 ade7753_write_8bit,
306 ADE7753_CFNUM);
307static IIO_DEV_ATTR_CHKSUM(ade7753_read_8bit, ADE7753_CHKSUM);
308static IIO_DEV_ATTR_PHCAL(S_IWUSR | S_IRUGO,
309 ade7753_read_16bit,
310 ade7753_write_16bit,
311 ADE7753_PHCAL);
312static IIO_DEV_ATTR_APOS(S_IWUSR | S_IRUGO,
313 ade7753_read_16bit,
314 ade7753_write_16bit,
315 ADE7753_APOS);
316static IIO_DEV_ATTR_SAGCYC(S_IWUSR | S_IRUGO,
317 ade7753_read_8bit,
318 ade7753_write_8bit,
319 ADE7753_SAGCYC);
320static IIO_DEV_ATTR_SAGLVL(S_IWUSR | S_IRUGO,
321 ade7753_read_8bit,
322 ade7753_write_8bit,
323 ADE7753_SAGLVL);
324static IIO_DEV_ATTR_LINECYC(S_IWUSR | S_IRUGO,
325 ade7753_read_8bit,
326 ade7753_write_8bit,
327 ADE7753_LINECYC);
328static IIO_DEV_ATTR_WDIV(S_IWUSR | S_IRUGO,
329 ade7753_read_8bit,
330 ade7753_write_8bit,
331 ADE7753_WDIV);
332static IIO_DEV_ATTR_IRMS(S_IWUSR | S_IRUGO,
333 ade7753_read_24bit,
334 NULL,
335 ADE7753_IRMS);
336static IIO_DEV_ATTR_VRMS(S_IRUGO,
337 ade7753_read_24bit,
338 NULL,
339 ADE7753_VRMS);
340static IIO_DEV_ATTR_IRMSOS(S_IWUSR | S_IRUGO,
341 ade7753_read_16bit,
342 ade7753_write_16bit,
343 ADE7753_IRMSOS);
344static IIO_DEV_ATTR_VRMSOS(S_IWUSR | S_IRUGO,
345 ade7753_read_16bit,
346 ade7753_write_16bit,
347 ADE7753_VRMSOS);
348static IIO_DEV_ATTR_WGAIN(S_IWUSR | S_IRUGO,
349 ade7753_read_16bit,
350 ade7753_write_16bit,
351 ADE7753_WGAIN);
352static IIO_DEV_ATTR_VAGAIN(S_IWUSR | S_IRUGO,
353 ade7753_read_16bit,
354 ade7753_write_16bit,
355 ADE7753_VAGAIN);
356static IIO_DEV_ATTR_PGA_GAIN(S_IWUSR | S_IRUGO,
357 ade7753_read_16bit,
358 ade7753_write_16bit,
359 ADE7753_GAIN);
360static IIO_DEV_ATTR_IPKLVL(S_IWUSR | S_IRUGO,
361 ade7753_read_8bit,
362 ade7753_write_8bit,
363 ADE7753_IPKLVL);
364static IIO_DEV_ATTR_VPKLVL(S_IWUSR | S_IRUGO,
365 ade7753_read_8bit,
366 ade7753_write_8bit,
367 ADE7753_VPKLVL);
368static IIO_DEV_ATTR_IPEAK(S_IRUGO,
369 ade7753_read_24bit,
370 NULL,
371 ADE7753_IPEAK);
372static IIO_DEV_ATTR_VPEAK(S_IRUGO,
373 ade7753_read_24bit,
374 NULL,
375 ADE7753_VPEAK);
376static IIO_DEV_ATTR_VPERIOD(S_IRUGO,
377 ade7753_read_16bit,
378 NULL,
379 ADE7753_PERIOD);
380static IIO_DEV_ATTR_CH_OFF(1, S_IWUSR | S_IRUGO,
381 ade7753_read_8bit,
382 ade7753_write_8bit,
383 ADE7753_CH1OS);
384static IIO_DEV_ATTR_CH_OFF(2, S_IWUSR | S_IRUGO,
385 ade7753_read_8bit,
386 ade7753_write_8bit,
387 ADE7753_CH2OS);
388
389static int ade7753_set_irq(struct device *dev, bool enable)
390{
391 int ret;
392 u8 irqen;
393 ret = ade7753_spi_read_reg_8(dev, ADE7753_IRQEN, &irqen);
394 if (ret)
395 goto error_ret;
396
397 if (enable)
398 irqen |= 1 << 3; /* Enables an interrupt when a data is
399 present in the waveform register */
400 else
401 irqen &= ~(1 << 3);
402
403 ret = ade7753_spi_write_reg_8(dev, ADE7753_IRQEN, irqen);
404 if (ret)
405 goto error_ret;
406
407error_ret:
408 return ret;
409}
410
411/* Power down the device */
412int ade7753_stop_device(struct device *dev)
413{
414 int ret;
415 u16 val;
416 ade7753_spi_read_reg_16(dev,
417 ADE7753_MODE,
418 &val);
419 val |= 1 << 4; /* AD converters can be turned off */
420 ret = ade7753_spi_write_reg_16(dev,
421 ADE7753_MODE,
422 val);
423
424 return ret;
425}
426
427static int ade7753_initial_setup(struct ade7753_state *st)
428{
429 int ret;
430 struct device *dev = &st->indio_dev->dev;
431
432 /* use low spi speed for init */
433 st->us->mode = SPI_MODE_3;
434 spi_setup(st->us);
435
436 /* Disable IRQ */
437 ret = ade7753_set_irq(dev, false);
438 if (ret) {
439 dev_err(dev, "disable irq failed");
440 goto err_ret;
441 }
442
443 ade7753_reset(dev);
444 msleep(ADE7753_STARTUP_DELAY);
445
446err_ret:
447 return ret;
448}
449
450static ssize_t ade7753_read_frequency(struct device *dev,
451 struct device_attribute *attr,
452 char *buf)
453{
454 int ret, len = 0;
455 u8 t;
456 int sps;
457 ret = ade7753_spi_read_reg_8(dev,
458 ADE7753_MODE,
459 &t);
460 if (ret)
461 return ret;
462
463 t = (t >> 11) & 0x3;
464 sps = 27900 / (1 + t);
465
466 len = sprintf(buf, "%d SPS\n", sps);
467 return len;
468}
469
470static ssize_t ade7753_write_frequency(struct device *dev,
471 struct device_attribute *attr,
472 const char *buf,
473 size_t len)
474{
475 struct iio_dev *indio_dev = dev_get_drvdata(dev);
476 struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
477 unsigned long val;
478 int ret;
479 u16 reg, t;
480
481 ret = strict_strtol(buf, 10, &val);
482 if (ret)
483 return ret;
484
485 mutex_lock(&indio_dev->mlock);
486
487 t = (27900 / val);
488 if (t > 0)
489 t--;
490
491 if (t > 1)
492 st->us->max_speed_hz = ADE7753_SPI_SLOW;
493 else
494 st->us->max_speed_hz = ADE7753_SPI_FAST;
495
496 ret = ade7753_spi_read_reg_16(dev,
497 ADE7753_MODE,
498 &reg);
499 if (ret)
500 goto out;
501
502 reg &= ~(3 << 11);
503 reg |= t << 11;
504
505 ret = ade7753_spi_write_reg_16(dev,
506 ADE7753_MODE,
507 reg);
508
509out:
510 mutex_unlock(&indio_dev->mlock);
511
512 return ret ? ret : len;
513}
514static IIO_DEV_ATTR_TEMP_RAW(ade7753_read_8bit);
515static IIO_CONST_ATTR(temp_offset, "-25 C");
516static IIO_CONST_ATTR(temp_scale, "0.67 C");
517
518static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
519 ade7753_read_frequency,
520 ade7753_write_frequency);
521
522static IIO_DEV_ATTR_RESET(ade7753_write_reset);
523
524static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500");
525
526static IIO_CONST_ATTR(name, "ade7753");
527
528static struct attribute *ade7753_event_attributes[] = {
529 NULL
530};
531
532static struct attribute_group ade7753_event_attribute_group = {
533 .attrs = ade7753_event_attributes,
534};
535
536static struct attribute *ade7753_attributes[] = {
537 &iio_dev_attr_temp_raw.dev_attr.attr,
538 &iio_const_attr_temp_offset.dev_attr.attr,
539 &iio_const_attr_temp_scale.dev_attr.attr,
540 &iio_dev_attr_sampling_frequency.dev_attr.attr,
541 &iio_const_attr_sampling_frequency_available.dev_attr.attr,
542 &iio_dev_attr_reset.dev_attr.attr,
543 &iio_const_attr_name.dev_attr.attr,
544 &iio_dev_attr_phcal.dev_attr.attr,
545 &iio_dev_attr_cfden.dev_attr.attr,
546 &iio_dev_attr_aenergy.dev_attr.attr,
547 &iio_dev_attr_laenergy.dev_attr.attr,
548 &iio_dev_attr_vaenergy.dev_attr.attr,
549 &iio_dev_attr_lvaenergy.dev_attr.attr,
550 &iio_dev_attr_cfnum.dev_attr.attr,
551 &iio_dev_attr_apos.dev_attr.attr,
552 &iio_dev_attr_sagcyc.dev_attr.attr,
553 &iio_dev_attr_saglvl.dev_attr.attr,
554 &iio_dev_attr_linecyc.dev_attr.attr,
555 &iio_dev_attr_chksum.dev_attr.attr,
556 &iio_dev_attr_pga_gain.dev_attr.attr,
557 &iio_dev_attr_wgain.dev_attr.attr,
558 &iio_dev_attr_choff_1.dev_attr.attr,
559 &iio_dev_attr_choff_2.dev_attr.attr,
560 &iio_dev_attr_wdiv.dev_attr.attr,
561 &iio_dev_attr_irms.dev_attr.attr,
562 &iio_dev_attr_vrms.dev_attr.attr,
563 &iio_dev_attr_irmsos.dev_attr.attr,
564 &iio_dev_attr_vrmsos.dev_attr.attr,
565 &iio_dev_attr_vagain.dev_attr.attr,
566 &iio_dev_attr_ipklvl.dev_attr.attr,
567 &iio_dev_attr_vpklvl.dev_attr.attr,
568 &iio_dev_attr_ipeak.dev_attr.attr,
569 &iio_dev_attr_vpeak.dev_attr.attr,
570 &iio_dev_attr_vperiod.dev_attr.attr,
571 NULL,
572};
573
574static const struct attribute_group ade7753_attribute_group = {
575 .attrs = ade7753_attributes,
576};
577
578static int __devinit ade7753_probe(struct spi_device *spi)
579{
580 int ret, regdone = 0;
581 struct ade7753_state *st = kzalloc(sizeof *st, GFP_KERNEL);
582 if (!st) {
583 ret = -ENOMEM;
584 goto error_ret;
585 }
586 /* this is only used for removal purposes */
587 spi_set_drvdata(spi, st);
588
589 /* Allocate the comms buffers */
590 st->rx = kzalloc(sizeof(*st->rx)*ADE7753_MAX_RX, GFP_KERNEL);
591 if (st->rx == NULL) {
592 ret = -ENOMEM;
593 goto error_free_st;
594 }
595 st->tx = kzalloc(sizeof(*st->tx)*ADE7753_MAX_TX, GFP_KERNEL);
596 if (st->tx == NULL) {
597 ret = -ENOMEM;
598 goto error_free_rx;
599 }
600 st->us = spi;
601 mutex_init(&st->buf_lock);
602 /* setup the industrialio driver allocated elements */
603 st->indio_dev = iio_allocate_device();
604 if (st->indio_dev == NULL) {
605 ret = -ENOMEM;
606 goto error_free_tx;
607 }
608
609 st->indio_dev->dev.parent = &spi->dev;
610 st->indio_dev->num_interrupt_lines = 1;
611 st->indio_dev->event_attrs = &ade7753_event_attribute_group;
612 st->indio_dev->attrs = &ade7753_attribute_group;
613 st->indio_dev->dev_data = (void *)(st);
614 st->indio_dev->driver_module = THIS_MODULE;
615 st->indio_dev->modes = INDIO_DIRECT_MODE;
616
617 ret = ade7753_configure_ring(st->indio_dev);
618 if (ret)
619 goto error_free_dev;
620
621 ret = iio_device_register(st->indio_dev);
622 if (ret)
623 goto error_unreg_ring_funcs;
624 regdone = 1;
625
626 ret = ade7753_initialize_ring(st->indio_dev->ring);
627 if (ret) {
628 printk(KERN_ERR "failed to initialize the ring\n");
629 goto error_unreg_ring_funcs;
630 }
631
632 if (spi->irq) {
633 ret = iio_register_interrupt_line(spi->irq,
634 st->indio_dev,
635 0,
636 IRQF_TRIGGER_FALLING,
637 "ade7753");
638 if (ret)
639 goto error_uninitialize_ring;
640
641 ret = ade7753_probe_trigger(st->indio_dev);
642 if (ret)
643 goto error_unregister_line;
644 }
645
646 /* Get the device into a sane initial state */
647 ret = ade7753_initial_setup(st);
648 if (ret)
649 goto error_remove_trigger;
650 return 0;
651
652error_remove_trigger:
653 if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
654 ade7753_remove_trigger(st->indio_dev);
655error_unregister_line:
656 if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
657 iio_unregister_interrupt_line(st->indio_dev, 0);
658error_uninitialize_ring:
659 ade7753_uninitialize_ring(st->indio_dev->ring);
660error_unreg_ring_funcs:
661 ade7753_unconfigure_ring(st->indio_dev);
662error_free_dev:
663 if (regdone)
664 iio_device_unregister(st->indio_dev);
665 else
666 iio_free_device(st->indio_dev);
667error_free_tx:
668 kfree(st->tx);
669error_free_rx:
670 kfree(st->rx);
671error_free_st:
672 kfree(st);
673error_ret:
674 return ret;
675}
676
677/* fixme, confirm ordering in this function */
678static int ade7753_remove(struct spi_device *spi)
679{
680 int ret;
681 struct ade7753_state *st = spi_get_drvdata(spi);
682 struct iio_dev *indio_dev = st->indio_dev;
683
684 ret = ade7753_stop_device(&(indio_dev->dev));
685 if (ret)
686 goto err_ret;
687
688 flush_scheduled_work();
689
690 ade7753_remove_trigger(indio_dev);
691 if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
692 iio_unregister_interrupt_line(indio_dev, 0);
693
694 ade7753_uninitialize_ring(indio_dev->ring);
695 ade7753_unconfigure_ring(indio_dev);
696 iio_device_unregister(indio_dev);
697 kfree(st->tx);
698 kfree(st->rx);
699 kfree(st);
700
701 return 0;
702
703err_ret:
704 return ret;
705}
706
707static struct spi_driver ade7753_driver = {
708 .driver = {
709 .name = "ade7753",
710 .owner = THIS_MODULE,
711 },
712 .probe = ade7753_probe,
713 .remove = __devexit_p(ade7753_remove),
714};
715
716static __init int ade7753_init(void)
717{
718 return spi_register_driver(&ade7753_driver);
719}
720module_init(ade7753_init);
721
722static __exit void ade7753_exit(void)
723{
724 spi_unregister_driver(&ade7753_driver);
725}
726module_exit(ade7753_exit);
727
728MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
729MODULE_DESCRIPTION("Analog Devices ADE7753/6 Single-Phase Multifunction Metering IC Driver");
730MODULE_LICENSE("GPL v2");