staging: iio: meter: new driver for ADE7754 devices

Signed-off-by: Barry Song <barry.song@analog.com>
Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Barry Song 2010-10-27 21:44:15 -04:00 committed by Greg Kroah-Hartman
parent 09434ef7c2
commit 8d97a5877b
4 changed files with 925 additions and 0 deletions

View file

@ -9,3 +9,10 @@ config ADE7753
help
Say yes here to build support for Analog Devices ADE7753 Single-Phase Multifunction
Metering IC with di/dt Sensor Interface.
config ADE7754
tristate "Analog Devices ADE7754 Polyphase Multifunction Energy Metering IC Driver"
depends on SPI
help
Say yes here to build support for Analog Devices ADE7754 Polyphase
Multifunction Energy Metering IC Driver.

View file

@ -3,3 +3,4 @@
#
obj-$(CONFIG_ADE7753) += ade7753.o
obj-$(CONFIG_ADE7754) += ade7754.o

View file

@ -0,0 +1,756 @@
/*
* ADE7754 Polyphase Multifunction Energy Metering IC Driver
*
* Copyright 2010 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
#include "../iio.h"
#include "../sysfs.h"
#include "meter.h"
#include "ade7754.h"
static int ade7754_spi_write_reg_8(struct device *dev,
u8 reg_address,
u8 val)
{
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = ADE7754_WRITE_REG(reg_address);
st->tx[1] = val;
ret = spi_write(st->us, st->tx, 2);
mutex_unlock(&st->buf_lock);
return ret;
}
static int ade7754_spi_write_reg_16(struct device *dev,
u8 reg_address,
u16 value)
{
int ret;
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
struct spi_transfer xfers[] = {
{
.tx_buf = st->tx,
.bits_per_word = 8,
.len = 3,
}
};
mutex_lock(&st->buf_lock);
st->tx[0] = ADE7754_WRITE_REG(reg_address);
st->tx[1] = (value >> 8) & 0xFF;
st->tx[2] = value & 0xFF;
spi_message_init(&msg);
spi_message_add_tail(xfers, &msg);
ret = spi_sync(st->us, &msg);
mutex_unlock(&st->buf_lock);
return ret;
}
static int ade7754_spi_read_reg_8(struct device *dev,
u8 reg_address,
u8 *val)
{
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
int ret;
struct spi_transfer xfers[] = {
{
.tx_buf = st->tx,
.rx_buf = st->rx,
.bits_per_word = 8,
.len = 2,
},
};
mutex_lock(&st->buf_lock);
st->tx[0] = ADE7754_READ_REG(reg_address);
st->tx[1] = 0;
spi_message_init(&msg);
spi_message_add_tail(xfers, &msg);
ret = spi_sync(st->us, &msg);
if (ret) {
dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X",
reg_address);
goto error_ret;
}
*val = st->rx[1];
error_ret:
mutex_unlock(&st->buf_lock);
return ret;
}
static int ade7754_spi_read_reg_16(struct device *dev,
u8 reg_address,
u16 *val)
{
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
int ret;
struct spi_transfer xfers[] = {
{
.tx_buf = st->tx,
.rx_buf = st->rx,
.bits_per_word = 8,
.len = 3,
},
};
mutex_lock(&st->buf_lock);
st->tx[0] = ADE7754_READ_REG(reg_address);
st->tx[1] = 0;
st->tx[2] = 0;
spi_message_init(&msg);
spi_message_add_tail(xfers, &msg);
ret = spi_sync(st->us, &msg);
if (ret) {
dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
reg_address);
goto error_ret;
}
*val = (st->rx[1] << 8) | st->rx[2];
error_ret:
mutex_unlock(&st->buf_lock);
return ret;
}
static int ade7754_spi_read_reg_24(struct device *dev,
u8 reg_address,
u32 *val)
{
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
int ret;
struct spi_transfer xfers[] = {
{
.tx_buf = st->tx,
.rx_buf = st->rx,
.bits_per_word = 8,
.len = 4,
},
};
mutex_lock(&st->buf_lock);
st->tx[0] = ADE7754_READ_REG(reg_address);
st->tx[1] = 0;
st->tx[2] = 0;
st->tx[3] = 0;
spi_message_init(&msg);
spi_message_add_tail(xfers, &msg);
ret = spi_sync(st->us, &msg);
if (ret) {
dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X",
reg_address);
goto error_ret;
}
*val = (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3];
error_ret:
mutex_unlock(&st->buf_lock);
return ret;
}
static ssize_t ade7754_read_8bit(struct device *dev,
struct device_attribute *attr,
char *buf)
{
int ret;
u8 val = 0;
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = ade7754_spi_read_reg_8(dev, this_attr->address, &val);
if (ret)
return ret;
return sprintf(buf, "%u\n", val);
}
static ssize_t ade7754_read_16bit(struct device *dev,
struct device_attribute *attr,
char *buf)
{
int ret;
u16 val = 0;
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = ade7754_spi_read_reg_16(dev, this_attr->address, &val);
if (ret)
return ret;
return sprintf(buf, "%u\n", val);
}
static ssize_t ade7754_read_24bit(struct device *dev,
struct device_attribute *attr,
char *buf)
{
int ret;
u32 val = 0;
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = ade7754_spi_read_reg_24(dev, this_attr->address, &val);
if (ret)
return ret;
return sprintf(buf, "%u\n", val & 0xFFFFFF);
}
static ssize_t ade7754_write_8bit(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
long val;
ret = strict_strtol(buf, 10, &val);
if (ret)
goto error_ret;
ret = ade7754_spi_write_reg_8(dev, this_attr->address, val);
error_ret:
return ret ? ret : len;
}
static ssize_t ade7754_write_16bit(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
long val;
ret = strict_strtol(buf, 10, &val);
if (ret)
goto error_ret;
ret = ade7754_spi_write_reg_16(dev, this_attr->address, val);
error_ret:
return ret ? ret : len;
}
static int ade7754_reset(struct device *dev)
{
int ret;
u8 val;
ade7754_spi_read_reg_8(dev,
ADE7754_OPMODE,
&val);
val |= 1 << 6; /* Software Chip Reset */
ret = ade7754_spi_write_reg_8(dev,
ADE7754_OPMODE,
val);
return ret;
}
static ssize_t ade7754_write_reset(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
if (len < 1)
return -1;
switch (buf[0]) {
case '1':
case 'y':
case 'Y':
return ade7754_reset(dev);
}
return -1;
}
static IIO_DEV_ATTR_AENERGY(ade7754_read_24bit, ADE7754_AENERGY);
static IIO_DEV_ATTR_LAENERGY(ade7754_read_24bit, ADE7754_LAENERGY);
static IIO_DEV_ATTR_VAENERGY(ade7754_read_24bit, ADE7754_VAENERGY);
static IIO_DEV_ATTR_LVAENERGY(ade7754_read_24bit, ADE7754_LVAENERGY);
static IIO_DEV_ATTR_VPEAK(S_IWUSR | S_IRUGO,
ade7754_read_8bit,
ade7754_write_8bit,
ADE7754_VPEAK);
static IIO_DEV_ATTR_IPEAK(S_IWUSR | S_IRUGO,
ade7754_read_8bit,
ade7754_write_8bit,
ADE7754_VPEAK);
static IIO_DEV_ATTR_APHCAL(S_IWUSR | S_IRUGO,
ade7754_read_8bit,
ade7754_write_8bit,
ADE7754_APHCAL);
static IIO_DEV_ATTR_BPHCAL(S_IWUSR | S_IRUGO,
ade7754_read_8bit,
ade7754_write_8bit,
ADE7754_BPHCAL);
static IIO_DEV_ATTR_CPHCAL(S_IWUSR | S_IRUGO,
ade7754_read_8bit,
ade7754_write_8bit,
ADE7754_CPHCAL);
static IIO_DEV_ATTR_AAPOS(S_IWUSR | S_IRUGO,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_AAPOS);
static IIO_DEV_ATTR_BAPOS(S_IWUSR | S_IRUGO,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_BAPOS);
static IIO_DEV_ATTR_CAPOS(S_IWUSR | S_IRUGO,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_CAPOS);
static IIO_DEV_ATTR_WDIV(S_IWUSR | S_IRUGO,
ade7754_read_8bit,
ade7754_write_8bit,
ADE7754_WDIV);
static IIO_DEV_ATTR_VADIV(S_IWUSR | S_IRUGO,
ade7754_read_8bit,
ade7754_write_8bit,
ADE7754_VADIV);
static IIO_DEV_ATTR_CFNUM(S_IWUSR | S_IRUGO,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_CFNUM);
static IIO_DEV_ATTR_CFDEN(S_IWUSR | S_IRUGO,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_CFDEN);
static IIO_DEV_ATTR_ACTIVE_POWER_A_GAIN(S_IWUSR | S_IRUGO,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_AAPGAIN);
static IIO_DEV_ATTR_ACTIVE_POWER_B_GAIN(S_IWUSR | S_IRUGO,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_BAPGAIN);
static IIO_DEV_ATTR_ACTIVE_POWER_C_GAIN(S_IWUSR | S_IRUGO,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_CAPGAIN);
static IIO_DEV_ATTR_AIRMS(S_IRUGO,
ade7754_read_24bit,
NULL,
ADE7754_AIRMS);
static IIO_DEV_ATTR_BIRMS(S_IRUGO,
ade7754_read_24bit,
NULL,
ADE7754_BIRMS);
static IIO_DEV_ATTR_CIRMS(S_IRUGO,
ade7754_read_24bit,
NULL,
ADE7754_CIRMS);
static IIO_DEV_ATTR_AVRMS(S_IRUGO,
ade7754_read_24bit,
NULL,
ADE7754_AVRMS);
static IIO_DEV_ATTR_BVRMS(S_IRUGO,
ade7754_read_24bit,
NULL,
ADE7754_BVRMS);
static IIO_DEV_ATTR_CVRMS(S_IRUGO,
ade7754_read_24bit,
NULL,
ADE7754_CVRMS);
static IIO_DEV_ATTR_AIRMSOS(S_IRUGO,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_AIRMSOS);
static IIO_DEV_ATTR_BIRMSOS(S_IRUGO,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_BIRMSOS);
static IIO_DEV_ATTR_CIRMSOS(S_IRUGO,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_CIRMSOS);
static IIO_DEV_ATTR_AVRMSOS(S_IRUGO,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_AVRMSOS);
static IIO_DEV_ATTR_BVRMSOS(S_IRUGO,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_BVRMSOS);
static IIO_DEV_ATTR_CVRMSOS(S_IRUGO,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_CVRMSOS);
static int ade7754_set_irq(struct device *dev, bool enable)
{
int ret;
u16 irqen;
ret = ade7754_spi_read_reg_16(dev, ADE7754_IRQEN, &irqen);
if (ret)
goto error_ret;
if (enable)
irqen |= 1 << 14; /* Enables an interrupt when a data is
present in the waveform register */
else
irqen &= ~(1 << 14);
ret = ade7754_spi_write_reg_16(dev, ADE7754_IRQEN, irqen);
if (ret)
goto error_ret;
error_ret:
return ret;
}
/* Power down the device */
static int ade7754_stop_device(struct device *dev)
{
int ret;
u8 val;
ade7754_spi_read_reg_8(dev,
ADE7754_OPMODE,
&val);
val |= 7 << 3; /* ADE7754 powered down */
ret = ade7754_spi_write_reg_8(dev,
ADE7754_OPMODE,
val);
return ret;
}
static int ade7754_initial_setup(struct ade7754_state *st)
{
int ret;
struct device *dev = &st->indio_dev->dev;
/* use low spi speed for init */
st->us->mode = SPI_MODE_3;
spi_setup(st->us);
/* Disable IRQ */
ret = ade7754_set_irq(dev, false);
if (ret) {
dev_err(dev, "disable irq failed");
goto err_ret;
}
ade7754_reset(dev);
msleep(ADE7754_STARTUP_DELAY);
err_ret:
return ret;
}
static ssize_t ade7754_read_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
{
int ret, len = 0;
u8 t;
int sps;
ret = ade7754_spi_read_reg_8(dev,
ADE7754_WAVMODE,
&t);
if (ret)
return ret;
t = (t >> 3) & 0x3;
sps = 26000 / (1 + t);
len = sprintf(buf, "%d SPS\n", sps);
return len;
}
static ssize_t ade7754_write_frequency(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
unsigned long val;
int ret;
u8 reg, t;
ret = strict_strtol(buf, 10, &val);
if (ret)
return ret;
mutex_lock(&indio_dev->mlock);
t = (26000 / val);
if (t > 0)
t--;
if (t > 1)
st->us->max_speed_hz = ADE7754_SPI_SLOW;
else
st->us->max_speed_hz = ADE7754_SPI_FAST;
ret = ade7754_spi_read_reg_8(dev,
ADE7754_WAVMODE,
&reg);
if (ret)
goto out;
reg &= ~(3 << 3);
reg |= t << 3;
ret = ade7754_spi_write_reg_8(dev,
ADE7754_WAVMODE,
reg);
out:
mutex_unlock(&indio_dev->mlock);
return ret ? ret : len;
}
static IIO_DEV_ATTR_TEMP_RAW(ade7754_read_8bit);
static IIO_CONST_ATTR(temp_offset, "129 C");
static IIO_CONST_ATTR(temp_scale, "4 C");
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
ade7754_read_frequency,
ade7754_write_frequency);
static IIO_DEV_ATTR_RESET(ade7754_write_reset);
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26000 13000 65000 33000");
static IIO_CONST_ATTR(name, "ade7754");
static struct attribute *ade7754_event_attributes[] = {
NULL
};
static struct attribute_group ade7754_event_attribute_group = {
.attrs = ade7754_event_attributes,
};
static struct attribute *ade7754_attributes[] = {
&iio_dev_attr_temp_raw.dev_attr.attr,
&iio_const_attr_temp_offset.dev_attr.attr,
&iio_const_attr_temp_scale.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
&iio_const_attr_name.dev_attr.attr,
&iio_dev_attr_aenergy.dev_attr.attr,
&iio_dev_attr_laenergy.dev_attr.attr,
&iio_dev_attr_vaenergy.dev_attr.attr,
&iio_dev_attr_lvaenergy.dev_attr.attr,
&iio_dev_attr_vpeak.dev_attr.attr,
&iio_dev_attr_ipeak.dev_attr.attr,
&iio_dev_attr_aphcal.dev_attr.attr,
&iio_dev_attr_bphcal.dev_attr.attr,
&iio_dev_attr_cphcal.dev_attr.attr,
&iio_dev_attr_aapos.dev_attr.attr,
&iio_dev_attr_bapos.dev_attr.attr,
&iio_dev_attr_capos.dev_attr.attr,
&iio_dev_attr_wdiv.dev_attr.attr,
&iio_dev_attr_vadiv.dev_attr.attr,
&iio_dev_attr_cfnum.dev_attr.attr,
&iio_dev_attr_cfden.dev_attr.attr,
&iio_dev_attr_active_power_a_gain.dev_attr.attr,
&iio_dev_attr_active_power_b_gain.dev_attr.attr,
&iio_dev_attr_active_power_c_gain.dev_attr.attr,
&iio_dev_attr_airms.dev_attr.attr,
&iio_dev_attr_birms.dev_attr.attr,
&iio_dev_attr_cirms.dev_attr.attr,
&iio_dev_attr_avrms.dev_attr.attr,
&iio_dev_attr_bvrms.dev_attr.attr,
&iio_dev_attr_cvrms.dev_attr.attr,
&iio_dev_attr_airmsos.dev_attr.attr,
&iio_dev_attr_birmsos.dev_attr.attr,
&iio_dev_attr_cirmsos.dev_attr.attr,
&iio_dev_attr_avrmsos.dev_attr.attr,
&iio_dev_attr_bvrmsos.dev_attr.attr,
&iio_dev_attr_cvrmsos.dev_attr.attr,
NULL,
};
static const struct attribute_group ade7754_attribute_group = {
.attrs = ade7754_attributes,
};
static int __devinit ade7754_probe(struct spi_device *spi)
{
int ret, regdone = 0;
struct ade7754_state *st = kzalloc(sizeof *st, GFP_KERNEL);
if (!st) {
ret = -ENOMEM;
goto error_ret;
}
/* this is only used for removal purposes */
spi_set_drvdata(spi, st);
/* Allocate the comms buffers */
st->rx = kzalloc(sizeof(*st->rx)*ADE7754_MAX_RX, GFP_KERNEL);
if (st->rx == NULL) {
ret = -ENOMEM;
goto error_free_st;
}
st->tx = kzalloc(sizeof(*st->tx)*ADE7754_MAX_TX, GFP_KERNEL);
if (st->tx == NULL) {
ret = -ENOMEM;
goto error_free_rx;
}
st->us = spi;
mutex_init(&st->buf_lock);
/* setup the industrialio driver allocated elements */
st->indio_dev = iio_allocate_device();
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_tx;
}
st->indio_dev->dev.parent = &spi->dev;
st->indio_dev->num_interrupt_lines = 1;
st->indio_dev->event_attrs = &ade7754_event_attribute_group;
st->indio_dev->attrs = &ade7754_attribute_group;
st->indio_dev->dev_data = (void *)(st);
st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = ade7754_configure_ring(st->indio_dev);
if (ret)
goto error_free_dev;
ret = iio_device_register(st->indio_dev);
if (ret)
goto error_unreg_ring_funcs;
regdone = 1;
ret = ade7754_initialize_ring(st->indio_dev->ring);
if (ret) {
printk(KERN_ERR "failed to initialize the ring\n");
goto error_unreg_ring_funcs;
}
if (spi->irq) {
ret = iio_register_interrupt_line(spi->irq,
st->indio_dev,
0,
IRQF_TRIGGER_FALLING,
"ade7754");
if (ret)
goto error_uninitialize_ring;
ret = ade7754_probe_trigger(st->indio_dev);
if (ret)
goto error_unregister_line;
}
/* Get the device into a sane initial state */
ret = ade7754_initial_setup(st);
if (ret)
goto error_remove_trigger;
return 0;
error_remove_trigger:
if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
ade7754_remove_trigger(st->indio_dev);
error_unregister_line:
if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
iio_unregister_interrupt_line(st->indio_dev, 0);
error_uninitialize_ring:
ade7754_uninitialize_ring(st->indio_dev->ring);
error_unreg_ring_funcs:
ade7754_unconfigure_ring(st->indio_dev);
error_free_dev:
if (regdone)
iio_device_unregister(st->indio_dev);
else
iio_free_device(st->indio_dev);
error_free_tx:
kfree(st->tx);
error_free_rx:
kfree(st->rx);
error_free_st:
kfree(st);
error_ret:
return ret;
}
/* fixme, confirm ordering in this function */
static int ade7754_remove(struct spi_device *spi)
{
int ret;
struct ade7754_state *st = spi_get_drvdata(spi);
struct iio_dev *indio_dev = st->indio_dev;
ret = ade7754_stop_device(&(indio_dev->dev));
if (ret)
goto err_ret;
flush_scheduled_work();
ade7754_remove_trigger(indio_dev);
if (spi->irq)
iio_unregister_interrupt_line(indio_dev, 0);
ade7754_uninitialize_ring(indio_dev->ring);
ade7754_unconfigure_ring(indio_dev);
iio_device_unregister(indio_dev);
kfree(st->tx);
kfree(st->rx);
kfree(st);
return 0;
err_ret:
return ret;
}
static struct spi_driver ade7754_driver = {
.driver = {
.name = "ade7754",
.owner = THIS_MODULE,
},
.probe = ade7754_probe,
.remove = __devexit_p(ade7754_remove),
};
static __init int ade7754_init(void)
{
return spi_register_driver(&ade7754_driver);
}
module_init(ade7754_init);
static __exit void ade7754_exit(void)
{
spi_unregister_driver(&ade7754_driver);
}
module_exit(ade7754_exit);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADE7754 Polyphase Multifunction Energy Metering IC Driver");
MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,161 @@
#ifndef _ADE7754_H
#define _ADE7754_H
#define ADE7754_AENERGY 0x01
#define ADE7754_RAENERGY 0x02
#define ADE7754_LAENERGY 0x03
#define ADE7754_VAENERGY 0x04
#define ADE7754_RVAENERGY 0x05
#define ADE7754_LVAENERGY 0x06
#define ADE7754_PERIOD 0x07
#define ADE7754_TEMP 0x08
#define ADE7754_WFORM 0x09
#define ADE7754_OPMODE 0x0A
#define ADE7754_MMODE 0x0B
#define ADE7754_WAVMODE 0x0C
#define ADE7754_WATMODE 0x0D
#define ADE7754_VAMODE 0x0E
#define ADE7754_IRQEN 0x0F
#define ADE7754_STATUS 0x10
#define ADE7754_RSTATUS 0x11
#define ADE7754_ZXTOUT 0x12
#define ADE7754_LINCYC 0x13
#define ADE7754_SAGCYC 0x14
#define ADE7754_SAGLVL 0x15
#define ADE7754_VPEAK 0x16
#define ADE7754_IPEAK 0x17
#define ADE7754_GAIN 0x18
#define ADE7754_AWG 0x19
#define ADE7754_BWG 0x1A
#define ADE7754_CWG 0x1B
#define ADE7754_AVAG 0x1C
#define ADE7754_BVAG 0x1D
#define ADE7754_CVAG 0x1E
#define ADE7754_APHCAL 0x1F
#define ADE7754_BPHCAL 0x20
#define ADE7754_CPHCAL 0x21
#define ADE7754_AAPOS 0x22
#define ADE7754_BAPOS 0x23
#define ADE7754_CAPOS 0x24
#define ADE7754_CFNUM 0x25
#define ADE7754_CFDEN 0x26
#define ADE7754_WDIV 0x27
#define ADE7754_VADIV 0x28
#define ADE7754_AIRMS 0x29
#define ADE7754_BIRMS 0x2A
#define ADE7754_CIRMS 0x2B
#define ADE7754_AVRMS 0x2C
#define ADE7754_BVRMS 0x2D
#define ADE7754_CVRMS 0x2E
#define ADE7754_AIRMSOS 0x2F
#define ADE7754_BIRMSOS 0x30
#define ADE7754_CIRMSOS 0x31
#define ADE7754_AVRMSOS 0x32
#define ADE7754_BVRMSOS 0x33
#define ADE7754_CVRMSOS 0x34
#define ADE7754_AAPGAIN 0x35
#define ADE7754_BAPGAIN 0x36
#define ADE7754_CAPGAIN 0x37
#define ADE7754_AVGAIN 0x38
#define ADE7754_BVGAIN 0x39
#define ADE7754_CVGAIN 0x3A
#define ADE7754_CHKSUM 0x3E
#define ADE7754_VERSION 0x3F
#define ADE7754_READ_REG(a) a
#define ADE7754_WRITE_REG(a) ((a) | 0x80)
#define ADE7754_MAX_TX 4
#define ADE7754_MAX_RX 4
#define ADE7754_STARTUP_DELAY 1
#define ADE7754_SPI_SLOW (u32)(300 * 1000)
#define ADE7754_SPI_BURST (u32)(1000 * 1000)
#define ADE7754_SPI_FAST (u32)(2000 * 1000)
#define DRIVER_NAME "ade7754"
/**
* struct ade7754_state - device instance specific data
* @us: actual spi_device
* @work_trigger_to_ring: bh for triggered event handling
* @inter: used to check if new interrupt has been triggered
* @last_timestamp: passing timestamp from th to bh of interrupt handler
* @indio_dev: industrial I/O device structure
* @trig: data ready trigger registered with iio
* @tx: transmit buffer
* @rx: recieve buffer
* @buf_lock: mutex to protect tx and rx
**/
struct ade7754_state {
struct spi_device *us;
struct work_struct work_trigger_to_ring;
s64 last_timestamp;
struct iio_dev *indio_dev;
struct iio_trigger *trig;
u8 *tx;
u8 *rx;
struct mutex buf_lock;
};
#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT)
/* At the moment triggers are only used for ring buffer
* filling. This may change!
*/
enum ade7754_scan {
ADE7754_SCAN_PHA_V,
ADE7754_SCAN_PHB_V,
ADE7754_SCAN_PHC_V,
ADE7754_SCAN_PHA_I,
ADE7754_SCAN_PHB_I,
ADE7754_SCAN_PHC_I,
};
void ade7754_remove_trigger(struct iio_dev *indio_dev);
int ade7754_probe_trigger(struct iio_dev *indio_dev);
ssize_t ade7754_read_data_from_ring(struct device *dev,
struct device_attribute *attr,
char *buf);
int ade7754_configure_ring(struct iio_dev *indio_dev);
void ade7754_unconfigure_ring(struct iio_dev *indio_dev);
int ade7754_initialize_ring(struct iio_ring_buffer *ring);
void ade7754_uninitialize_ring(struct iio_ring_buffer *ring);
#else /* CONFIG_IIO_RING_BUFFER */
static inline void ade7754_remove_trigger(struct iio_dev *indio_dev)
{
}
static inline int ade7754_probe_trigger(struct iio_dev *indio_dev)
{
return 0;
}
static inline ssize_t
ade7754_read_data_from_ring(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return 0;
}
static int ade7754_configure_ring(struct iio_dev *indio_dev)
{
return 0;
}
static inline void ade7754_unconfigure_ring(struct iio_dev *indio_dev)
{
}
static inline int ade7754_initialize_ring(struct iio_ring_buffer *ring)
{
return 0;
}
static inline void ade7754_uninitialize_ring(struct iio_ring_buffer *ring)
{
}
#endif /* CONFIG_IIO_RING_BUFFER */
#endif