1/*
2 * ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC 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/delay.h>
12#include <linux/mutex.h>
13#include <linux/device.h>
14#include <linux/kernel.h>
15#include <linux/slab.h>
16#include <linux/sysfs.h>
17#include <linux/list.h>
18#include <linux/module.h>
19
20#include <linux/iio/iio.h>
21#include <linux/iio/sysfs.h>
22#include "meter.h"
23#include "ade7854.h"
24
25static ssize_t ade7854_read_8bit(struct device *dev,
26		struct device_attribute *attr,
27		char *buf)
28{
29	int ret;
30	u8 val = 0;
31	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
32	struct ade7854_state *st = iio_priv(indio_dev);
33	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
34
35	ret = st->read_reg_8(dev, this_attr->address, &val);
36	if (ret)
37		return ret;
38
39	return sprintf(buf, "%u\n", val);
40}
41
42static ssize_t ade7854_read_16bit(struct device *dev,
43		struct device_attribute *attr,
44		char *buf)
45{
46	int ret;
47	u16 val = 0;
48	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
49	struct ade7854_state *st = iio_priv(indio_dev);
50	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
51
52	ret = st->read_reg_16(dev, this_attr->address, &val);
53	if (ret)
54		return ret;
55
56	return sprintf(buf, "%u\n", val);
57}
58
59static ssize_t ade7854_read_24bit(struct device *dev,
60		struct device_attribute *attr,
61		char *buf)
62{
63	int ret;
64	u32 val;
65	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
66	struct ade7854_state *st = iio_priv(indio_dev);
67	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
68
69	ret = st->read_reg_24(dev, this_attr->address, &val);
70	if (ret)
71		return ret;
72
73	return sprintf(buf, "%u\n", val);
74}
75
76static ssize_t ade7854_read_32bit(struct device *dev,
77		struct device_attribute *attr,
78		char *buf)
79{
80	int ret;
81	u32 val = 0;
82	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
83	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
84	struct ade7854_state *st = iio_priv(indio_dev);
85
86	ret = st->read_reg_32(dev, this_attr->address, &val);
87	if (ret)
88		return ret;
89
90	return sprintf(buf, "%u\n", val);
91}
92
93static ssize_t ade7854_write_8bit(struct device *dev,
94		struct device_attribute *attr,
95		const char *buf,
96		size_t len)
97{
98	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
99	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
100	struct ade7854_state *st = iio_priv(indio_dev);
101
102	int ret;
103	u8 val;
104
105	ret = kstrtou8(buf, 10, &val);
106	if (ret)
107		goto error_ret;
108	ret = st->write_reg_8(dev, this_attr->address, val);
109
110error_ret:
111	return ret ? ret : len;
112}
113
114static ssize_t ade7854_write_16bit(struct device *dev,
115		struct device_attribute *attr,
116		const char *buf,
117		size_t len)
118{
119	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
120	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
121	struct ade7854_state *st = iio_priv(indio_dev);
122
123	int ret;
124	u16 val;
125
126	ret = kstrtou16(buf, 10, &val);
127	if (ret)
128		goto error_ret;
129	ret = st->write_reg_16(dev, this_attr->address, val);
130
131error_ret:
132	return ret ? ret : len;
133}
134
135static ssize_t ade7854_write_24bit(struct device *dev,
136		struct device_attribute *attr,
137		const char *buf,
138		size_t len)
139{
140	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
141	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
142	struct ade7854_state *st = iio_priv(indio_dev);
143
144	int ret;
145	u32 val;
146
147	ret = kstrtou32(buf, 10, &val);
148	if (ret)
149		goto error_ret;
150	ret = st->write_reg_24(dev, this_attr->address, val);
151
152error_ret:
153	return ret ? ret : len;
154}
155
156static ssize_t ade7854_write_32bit(struct device *dev,
157		struct device_attribute *attr,
158		const char *buf,
159		size_t len)
160{
161	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
162	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
163	struct ade7854_state *st = iio_priv(indio_dev);
164
165	int ret;
166	u32 val;
167
168	ret = kstrtou32(buf, 10, &val);
169	if (ret)
170		goto error_ret;
171	ret = st->write_reg_32(dev, this_attr->address, val);
172
173error_ret:
174	return ret ? ret : len;
175}
176
177static int ade7854_reset(struct device *dev)
178{
179	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
180	struct ade7854_state *st = iio_priv(indio_dev);
181	u16 val;
182
183	st->read_reg_16(dev, ADE7854_CONFIG, &val);
184	val |= 1 << 7; /* Software Chip Reset */
185
186	return st->write_reg_16(dev, ADE7854_CONFIG, val);
187}
188
189static IIO_DEV_ATTR_AIGAIN(S_IWUSR | S_IRUGO,
190		ade7854_read_24bit,
191		ade7854_write_24bit,
192		ADE7854_AIGAIN);
193static IIO_DEV_ATTR_BIGAIN(S_IWUSR | S_IRUGO,
194		ade7854_read_24bit,
195		ade7854_write_24bit,
196		ADE7854_BIGAIN);
197static IIO_DEV_ATTR_CIGAIN(S_IWUSR | S_IRUGO,
198		ade7854_read_24bit,
199		ade7854_write_24bit,
200		ADE7854_CIGAIN);
201static IIO_DEV_ATTR_NIGAIN(S_IWUSR | S_IRUGO,
202		ade7854_read_24bit,
203		ade7854_write_24bit,
204		ADE7854_NIGAIN);
205static IIO_DEV_ATTR_AVGAIN(S_IWUSR | S_IRUGO,
206		ade7854_read_24bit,
207		ade7854_write_24bit,
208		ADE7854_AVGAIN);
209static IIO_DEV_ATTR_BVGAIN(S_IWUSR | S_IRUGO,
210		ade7854_read_24bit,
211		ade7854_write_24bit,
212		ADE7854_BVGAIN);
213static IIO_DEV_ATTR_CVGAIN(S_IWUSR | S_IRUGO,
214		ade7854_read_24bit,
215		ade7854_write_24bit,
216		ADE7854_CVGAIN);
217static IIO_DEV_ATTR_APPARENT_POWER_A_GAIN(S_IWUSR | S_IRUGO,
218		ade7854_read_24bit,
219		ade7854_write_24bit,
220		ADE7854_AVAGAIN);
221static IIO_DEV_ATTR_APPARENT_POWER_B_GAIN(S_IWUSR | S_IRUGO,
222		ade7854_read_24bit,
223		ade7854_write_24bit,
224		ADE7854_BVAGAIN);
225static IIO_DEV_ATTR_APPARENT_POWER_C_GAIN(S_IWUSR | S_IRUGO,
226		ade7854_read_24bit,
227		ade7854_write_24bit,
228		ADE7854_CVAGAIN);
229static IIO_DEV_ATTR_ACTIVE_POWER_A_OFFSET(S_IWUSR | S_IRUGO,
230		ade7854_read_24bit,
231		ade7854_write_24bit,
232		ADE7854_AWATTOS);
233static IIO_DEV_ATTR_ACTIVE_POWER_B_OFFSET(S_IWUSR | S_IRUGO,
234		ade7854_read_24bit,
235		ade7854_write_24bit,
236		ADE7854_BWATTOS);
237static IIO_DEV_ATTR_ACTIVE_POWER_C_OFFSET(S_IWUSR | S_IRUGO,
238		ade7854_read_24bit,
239		ade7854_write_24bit,
240		ADE7854_CWATTOS);
241static IIO_DEV_ATTR_REACTIVE_POWER_A_GAIN(S_IWUSR | S_IRUGO,
242		ade7854_read_24bit,
243		ade7854_write_24bit,
244		ADE7854_AVARGAIN);
245static IIO_DEV_ATTR_REACTIVE_POWER_B_GAIN(S_IWUSR | S_IRUGO,
246		ade7854_read_24bit,
247		ade7854_write_24bit,
248		ADE7854_BVARGAIN);
249static IIO_DEV_ATTR_REACTIVE_POWER_C_GAIN(S_IWUSR | S_IRUGO,
250		ade7854_read_24bit,
251		ade7854_write_24bit,
252		ADE7854_CVARGAIN);
253static IIO_DEV_ATTR_REACTIVE_POWER_A_OFFSET(S_IWUSR | S_IRUGO,
254		ade7854_read_24bit,
255		ade7854_write_24bit,
256		ADE7854_AVAROS);
257static IIO_DEV_ATTR_REACTIVE_POWER_B_OFFSET(S_IWUSR | S_IRUGO,
258		ade7854_read_24bit,
259		ade7854_write_24bit,
260		ADE7854_BVAROS);
261static IIO_DEV_ATTR_REACTIVE_POWER_C_OFFSET(S_IWUSR | S_IRUGO,
262		ade7854_read_24bit,
263		ade7854_write_24bit,
264		ADE7854_CVAROS);
265static IIO_DEV_ATTR_VPEAK(S_IWUSR | S_IRUGO,
266		ade7854_read_32bit,
267		ade7854_write_32bit,
268		ADE7854_VPEAK);
269static IIO_DEV_ATTR_IPEAK(S_IWUSR | S_IRUGO,
270		ade7854_read_32bit,
271		ade7854_write_32bit,
272		ADE7854_VPEAK);
273static IIO_DEV_ATTR_APHCAL(S_IWUSR | S_IRUGO,
274		ade7854_read_16bit,
275		ade7854_write_16bit,
276		ADE7854_APHCAL);
277static IIO_DEV_ATTR_BPHCAL(S_IWUSR | S_IRUGO,
278		ade7854_read_16bit,
279		ade7854_write_16bit,
280		ADE7854_BPHCAL);
281static IIO_DEV_ATTR_CPHCAL(S_IWUSR | S_IRUGO,
282		ade7854_read_16bit,
283		ade7854_write_16bit,
284		ADE7854_CPHCAL);
285static IIO_DEV_ATTR_CF1DEN(S_IWUSR | S_IRUGO,
286		ade7854_read_16bit,
287		ade7854_write_16bit,
288		ADE7854_CF1DEN);
289static IIO_DEV_ATTR_CF2DEN(S_IWUSR | S_IRUGO,
290		ade7854_read_16bit,
291		ade7854_write_16bit,
292		ADE7854_CF2DEN);
293static IIO_DEV_ATTR_CF3DEN(S_IWUSR | S_IRUGO,
294		ade7854_read_16bit,
295		ade7854_write_16bit,
296		ADE7854_CF3DEN);
297static IIO_DEV_ATTR_LINECYC(S_IWUSR | S_IRUGO,
298		ade7854_read_16bit,
299		ade7854_write_16bit,
300		ADE7854_LINECYC);
301static IIO_DEV_ATTR_SAGCYC(S_IWUSR | S_IRUGO,
302		ade7854_read_8bit,
303		ade7854_write_8bit,
304		ADE7854_SAGCYC);
305static IIO_DEV_ATTR_CFCYC(S_IWUSR | S_IRUGO,
306		ade7854_read_8bit,
307		ade7854_write_8bit,
308		ADE7854_CFCYC);
309static IIO_DEV_ATTR_PEAKCYC(S_IWUSR | S_IRUGO,
310		ade7854_read_8bit,
311		ade7854_write_8bit,
312		ADE7854_PEAKCYC);
313static IIO_DEV_ATTR_CHKSUM(ade7854_read_24bit,
314		ADE7854_CHECKSUM);
315static IIO_DEV_ATTR_ANGLE0(ade7854_read_24bit,
316		ADE7854_ANGLE0);
317static IIO_DEV_ATTR_ANGLE1(ade7854_read_24bit,
318		ADE7854_ANGLE1);
319static IIO_DEV_ATTR_ANGLE2(ade7854_read_24bit,
320		ADE7854_ANGLE2);
321static IIO_DEV_ATTR_AIRMS(S_IRUGO,
322		ade7854_read_24bit,
323		NULL,
324		ADE7854_AIRMS);
325static IIO_DEV_ATTR_BIRMS(S_IRUGO,
326		ade7854_read_24bit,
327		NULL,
328		ADE7854_BIRMS);
329static IIO_DEV_ATTR_CIRMS(S_IRUGO,
330		ade7854_read_24bit,
331		NULL,
332		ADE7854_CIRMS);
333static IIO_DEV_ATTR_NIRMS(S_IRUGO,
334		ade7854_read_24bit,
335		NULL,
336		ADE7854_NIRMS);
337static IIO_DEV_ATTR_AVRMS(S_IRUGO,
338		ade7854_read_24bit,
339		NULL,
340		ADE7854_AVRMS);
341static IIO_DEV_ATTR_BVRMS(S_IRUGO,
342		ade7854_read_24bit,
343		NULL,
344		ADE7854_BVRMS);
345static IIO_DEV_ATTR_CVRMS(S_IRUGO,
346		ade7854_read_24bit,
347		NULL,
348		ADE7854_CVRMS);
349static IIO_DEV_ATTR_AIRMSOS(S_IRUGO,
350		ade7854_read_16bit,
351		ade7854_write_16bit,
352		ADE7854_AIRMSOS);
353static IIO_DEV_ATTR_BIRMSOS(S_IRUGO,
354		ade7854_read_16bit,
355		ade7854_write_16bit,
356		ADE7854_BIRMSOS);
357static IIO_DEV_ATTR_CIRMSOS(S_IRUGO,
358		ade7854_read_16bit,
359		ade7854_write_16bit,
360		ADE7854_CIRMSOS);
361static IIO_DEV_ATTR_AVRMSOS(S_IRUGO,
362		ade7854_read_16bit,
363		ade7854_write_16bit,
364		ADE7854_AVRMSOS);
365static IIO_DEV_ATTR_BVRMSOS(S_IRUGO,
366		ade7854_read_16bit,
367		ade7854_write_16bit,
368		ADE7854_BVRMSOS);
369static IIO_DEV_ATTR_CVRMSOS(S_IRUGO,
370		ade7854_read_16bit,
371		ade7854_write_16bit,
372		ADE7854_CVRMSOS);
373static IIO_DEV_ATTR_VOLT_A(ade7854_read_24bit,
374		ADE7854_VAWV);
375static IIO_DEV_ATTR_VOLT_B(ade7854_read_24bit,
376		ADE7854_VBWV);
377static IIO_DEV_ATTR_VOLT_C(ade7854_read_24bit,
378		ADE7854_VCWV);
379static IIO_DEV_ATTR_CURRENT_A(ade7854_read_24bit,
380		ADE7854_IAWV);
381static IIO_DEV_ATTR_CURRENT_B(ade7854_read_24bit,
382		ADE7854_IBWV);
383static IIO_DEV_ATTR_CURRENT_C(ade7854_read_24bit,
384		ADE7854_ICWV);
385static IIO_DEV_ATTR_AWATTHR(ade7854_read_32bit,
386		ADE7854_AWATTHR);
387static IIO_DEV_ATTR_BWATTHR(ade7854_read_32bit,
388		ADE7854_BWATTHR);
389static IIO_DEV_ATTR_CWATTHR(ade7854_read_32bit,
390		ADE7854_CWATTHR);
391static IIO_DEV_ATTR_AFWATTHR(ade7854_read_32bit,
392		ADE7854_AFWATTHR);
393static IIO_DEV_ATTR_BFWATTHR(ade7854_read_32bit,
394		ADE7854_BFWATTHR);
395static IIO_DEV_ATTR_CFWATTHR(ade7854_read_32bit,
396		ADE7854_CFWATTHR);
397static IIO_DEV_ATTR_AVARHR(ade7854_read_32bit,
398		ADE7854_AVARHR);
399static IIO_DEV_ATTR_BVARHR(ade7854_read_32bit,
400		ADE7854_BVARHR);
401static IIO_DEV_ATTR_CVARHR(ade7854_read_32bit,
402		ADE7854_CVARHR);
403static IIO_DEV_ATTR_AVAHR(ade7854_read_32bit,
404		ADE7854_AVAHR);
405static IIO_DEV_ATTR_BVAHR(ade7854_read_32bit,
406		ADE7854_BVAHR);
407static IIO_DEV_ATTR_CVAHR(ade7854_read_32bit,
408		ADE7854_CVAHR);
409
410static int ade7854_set_irq(struct device *dev, bool enable)
411{
412	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
413	struct ade7854_state *st = iio_priv(indio_dev);
414
415	int ret;
416	u32 irqen;
417
418	ret = st->read_reg_32(dev, ADE7854_MASK0, &irqen);
419	if (ret)
420		goto error_ret;
421
422	if (enable)
423		irqen |= 1 << 17; /* 1: interrupt enabled when all periodical
424				     (at 8 kHz rate) DSP computations finish. */
425	else
426		irqen &= ~(1 << 17);
427
428	ret = st->write_reg_32(dev, ADE7854_MASK0, irqen);
429	if (ret)
430		goto error_ret;
431
432error_ret:
433	return ret;
434}
435
436static int ade7854_initial_setup(struct iio_dev *indio_dev)
437{
438	int ret;
439	struct device *dev = &indio_dev->dev;
440
441	/* Disable IRQ */
442	ret = ade7854_set_irq(dev, false);
443	if (ret) {
444		dev_err(dev, "disable irq failed");
445		goto err_ret;
446	}
447
448	ade7854_reset(dev);
449	msleep(ADE7854_STARTUP_DELAY);
450
451err_ret:
452	return ret;
453}
454
455static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("8000");
456
457static IIO_CONST_ATTR(name, "ade7854");
458
459static struct attribute *ade7854_attributes[] = {
460	&iio_dev_attr_aigain.dev_attr.attr,
461	&iio_dev_attr_bigain.dev_attr.attr,
462	&iio_dev_attr_cigain.dev_attr.attr,
463	&iio_dev_attr_nigain.dev_attr.attr,
464	&iio_dev_attr_avgain.dev_attr.attr,
465	&iio_dev_attr_bvgain.dev_attr.attr,
466	&iio_dev_attr_cvgain.dev_attr.attr,
467	&iio_dev_attr_linecyc.dev_attr.attr,
468	&iio_dev_attr_sagcyc.dev_attr.attr,
469	&iio_dev_attr_cfcyc.dev_attr.attr,
470	&iio_dev_attr_peakcyc.dev_attr.attr,
471	&iio_dev_attr_chksum.dev_attr.attr,
472	&iio_dev_attr_apparent_power_a_gain.dev_attr.attr,
473	&iio_dev_attr_apparent_power_b_gain.dev_attr.attr,
474	&iio_dev_attr_apparent_power_c_gain.dev_attr.attr,
475	&iio_dev_attr_active_power_a_offset.dev_attr.attr,
476	&iio_dev_attr_active_power_b_offset.dev_attr.attr,
477	&iio_dev_attr_active_power_c_offset.dev_attr.attr,
478	&iio_dev_attr_reactive_power_a_gain.dev_attr.attr,
479	&iio_dev_attr_reactive_power_b_gain.dev_attr.attr,
480	&iio_dev_attr_reactive_power_c_gain.dev_attr.attr,
481	&iio_dev_attr_reactive_power_a_offset.dev_attr.attr,
482	&iio_dev_attr_reactive_power_b_offset.dev_attr.attr,
483	&iio_dev_attr_reactive_power_c_offset.dev_attr.attr,
484	&iio_dev_attr_awatthr.dev_attr.attr,
485	&iio_dev_attr_bwatthr.dev_attr.attr,
486	&iio_dev_attr_cwatthr.dev_attr.attr,
487	&iio_dev_attr_afwatthr.dev_attr.attr,
488	&iio_dev_attr_bfwatthr.dev_attr.attr,
489	&iio_dev_attr_cfwatthr.dev_attr.attr,
490	&iio_dev_attr_avarhr.dev_attr.attr,
491	&iio_dev_attr_bvarhr.dev_attr.attr,
492	&iio_dev_attr_cvarhr.dev_attr.attr,
493	&iio_dev_attr_angle0.dev_attr.attr,
494	&iio_dev_attr_angle1.dev_attr.attr,
495	&iio_dev_attr_angle2.dev_attr.attr,
496	&iio_dev_attr_avahr.dev_attr.attr,
497	&iio_dev_attr_bvahr.dev_attr.attr,
498	&iio_dev_attr_cvahr.dev_attr.attr,
499	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
500	&iio_const_attr_name.dev_attr.attr,
501	&iio_dev_attr_vpeak.dev_attr.attr,
502	&iio_dev_attr_ipeak.dev_attr.attr,
503	&iio_dev_attr_aphcal.dev_attr.attr,
504	&iio_dev_attr_bphcal.dev_attr.attr,
505	&iio_dev_attr_cphcal.dev_attr.attr,
506	&iio_dev_attr_cf1den.dev_attr.attr,
507	&iio_dev_attr_cf2den.dev_attr.attr,
508	&iio_dev_attr_cf3den.dev_attr.attr,
509	&iio_dev_attr_airms.dev_attr.attr,
510	&iio_dev_attr_birms.dev_attr.attr,
511	&iio_dev_attr_cirms.dev_attr.attr,
512	&iio_dev_attr_nirms.dev_attr.attr,
513	&iio_dev_attr_avrms.dev_attr.attr,
514	&iio_dev_attr_bvrms.dev_attr.attr,
515	&iio_dev_attr_cvrms.dev_attr.attr,
516	&iio_dev_attr_airmsos.dev_attr.attr,
517	&iio_dev_attr_birmsos.dev_attr.attr,
518	&iio_dev_attr_cirmsos.dev_attr.attr,
519	&iio_dev_attr_avrmsos.dev_attr.attr,
520	&iio_dev_attr_bvrmsos.dev_attr.attr,
521	&iio_dev_attr_cvrmsos.dev_attr.attr,
522	&iio_dev_attr_volt_a.dev_attr.attr,
523	&iio_dev_attr_volt_b.dev_attr.attr,
524	&iio_dev_attr_volt_c.dev_attr.attr,
525	&iio_dev_attr_current_a.dev_attr.attr,
526	&iio_dev_attr_current_b.dev_attr.attr,
527	&iio_dev_attr_current_c.dev_attr.attr,
528	NULL,
529};
530
531static const struct attribute_group ade7854_attribute_group = {
532	.attrs = ade7854_attributes,
533};
534
535static const struct iio_info ade7854_info = {
536	.attrs = &ade7854_attribute_group,
537	.driver_module = THIS_MODULE,
538};
539
540int ade7854_probe(struct iio_dev *indio_dev, struct device *dev)
541{
542	int ret;
543	struct ade7854_state *st = iio_priv(indio_dev);
544	/* setup the industrialio driver allocated elements */
545	mutex_init(&st->buf_lock);
546
547	indio_dev->dev.parent = dev;
548	indio_dev->info = &ade7854_info;
549	indio_dev->modes = INDIO_DIRECT_MODE;
550
551	ret = iio_device_register(indio_dev);
552	if (ret)
553		return ret;
554
555	/* Get the device into a sane initial state */
556	ret = ade7854_initial_setup(indio_dev);
557	if (ret)
558		goto error_unreg_dev;
559
560	return 0;
561
562error_unreg_dev:
563	iio_device_unregister(indio_dev);
564	return ret;
565}
566EXPORT_SYMBOL(ade7854_probe);
567
568int ade7854_remove(struct iio_dev *indio_dev)
569{
570	iio_device_unregister(indio_dev);
571
572	return 0;
573}
574EXPORT_SYMBOL(ade7854_remove);
575
576MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
577MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Energy Meter");
578MODULE_LICENSE("GPL v2");
579