Title: [8585] trunk/drivers/staging/iio/meter: [#5906], ADE7854/ADE7858/ADE7868/ADE7878 Polyphase Multifunction Energy Metering IC IIO driver
Revision
8585
Author
bhsong
Date
2010-04-01 01:56:52 -0400 (Thu, 01 Apr 2010)

Log Message

[#5906], ADE7854/ADE7858/ADE7868/ADE7878 Polyphase Multifunction Energy Metering IC IIO driver

support both i2c and spi bus

Modified Paths

Added Paths

Diff

Modified: trunk/drivers/staging/iio/meter/Kconfig (8584 => 8585)


--- trunk/drivers/staging/iio/meter/Kconfig	2010-04-01 05:44:55 UTC (rev 8584)
+++ trunk/drivers/staging/iio/meter/Kconfig	2010-04-01 05:56:52 UTC (rev 8585)
@@ -38,3 +38,23 @@
 	  Say yes here to build support for Analog Devices ADE7854/58/68/78 Polyphase
 	  Multifunction Energy Metering IC Driver.
 
+config ADE7854_I2C
+	tristate "support I2C bus connection"
+	depends on ADE7854 && I2C
+	default y
+	help
+	  Say Y here if you have ADE7854/58/68/78 hooked to an I2C bus.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ade7854-i2c.
+
+config ADE7854_SPI
+	tristate "support SPI bus connection"
+	depends on ADE7854 && SPI
+	default y
+	help
+	  Say Y here if you have ADE7854/58/68/78 hooked to a SPI bus.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ade7854-spi.
+

Modified: trunk/drivers/staging/iio/meter/Makefile (8584 => 8585)


--- trunk/drivers/staging/iio/meter/Makefile	2010-04-01 05:44:55 UTC (rev 8584)
+++ trunk/drivers/staging/iio/meter/Makefile	2010-04-01 05:56:52 UTC (rev 8585)
@@ -7,3 +7,6 @@
 obj-$(CONFIG_ADE7758) += ade7758.o
 obj-$(CONFIG_ADE7759) += ade7759.o
 obj-$(CONFIG_ADE7854) += ade7854.o
+obj-$(CONFIG_ADE7854_I2C) += ade7854-i2c.o
+obj-$(CONFIG_ADE7854_SPI) += ade7854-spi.o
+

Added: trunk/drivers/staging/iio/meter/ade7854-i2c.c (0 => 8585)


--- trunk/drivers/staging/iio/meter/ade7854-i2c.c	                        (rev 0)
+++ trunk/drivers/staging/iio/meter/ade7854-i2c.c	2010-04-01 05:56:52 UTC (rev 8585)
@@ -0,0 +1,271 @@
+/*
+ * ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver (I2C Bus)
+ *
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+
+#include "../iio.h"
+#include "ade7854.h"
+
+static int ade7854_i2c_write_reg_8(struct device *dev,
+		u16 reg_address,
+		u8 value)
+{
+	int ret;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = (reg_address >> 8) & 0xFF;
+	st->tx[1] = reg_address & 0xFF;
+	st->tx[2] = value;
+
+	ret = i2c_master_send(st->i2c, st->tx, 3);
+	mutex_unlock(&st->buf_lock);
+
+	return ret;
+}
+
+static int ade7854_i2c_write_reg_16(struct device *dev,
+		u16 reg_address,
+		u16 value)
+{
+	int ret;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = (reg_address >> 8) & 0xFF;
+	st->tx[1] = reg_address & 0xFF;
+	st->tx[2] = (value >> 8) & 0xFF;
+	st->tx[3] = value & 0xFF;
+
+	ret = i2c_master_send(st->i2c, st->tx, 4);
+	mutex_unlock(&st->buf_lock);
+
+	return ret;
+}
+
+static int ade7854_i2c_write_reg_24(struct device *dev,
+		u16 reg_address,
+		u32 value)
+{
+	int ret;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = (reg_address >> 8) & 0xFF;
+	st->tx[1] = reg_address & 0xFF;
+	st->tx[2] = (value >> 16) & 0xFF;
+	st->tx[3] = (value >> 8) & 0xFF;
+	st->tx[4] = value & 0xFF;
+
+	ret = i2c_master_send(st->i2c, st->tx, 5);
+	mutex_unlock(&st->buf_lock);
+
+	return ret;
+}
+
+static int ade7854_i2c_write_reg_32(struct device *dev,
+		u16 reg_address,
+		u32 value)
+{
+	int ret;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = (reg_address >> 8) & 0xFF;
+	st->tx[1] = reg_address & 0xFF;
+	st->tx[2] = (value >> 24) & 0xFF;
+	st->tx[3] = (value >> 16) & 0xFF;
+	st->tx[4] = (value >> 8) & 0xFF;
+	st->tx[5] = value & 0xFF;
+
+	ret = i2c_master_send(st->i2c, st->tx, 6);
+	mutex_unlock(&st->buf_lock);
+
+	return ret;
+}
+
+static int ade7854_i2c_read_reg_8(struct device *dev,
+		u16 reg_address,
+		u8 *val)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	int ret;
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = (reg_address >> 8) & 0xFF;
+	st->tx[1] = reg_address & 0xFF;
+
+	ret = i2c_master_send(st->i2c, st->tx, 2);
+	if (ret)
+		goto out;
+
+	ret = i2c_master_recv(st->i2c, st->rx, 1);
+	if (ret)
+		goto out;
+
+	*val = st->rx[0];
+out:
+	mutex_unlock(&st->buf_lock);
+	return ret;
+}
+
+static int ade7854_i2c_read_reg_16(struct device *dev,
+		u16 reg_address,
+		u16 *val)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	int ret;
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = (reg_address >> 8) & 0xFF;
+	st->tx[1] = reg_address & 0xFF;
+
+	ret = i2c_master_send(st->i2c, st->tx, 2);
+	if (ret)
+		goto out;
+
+	ret = i2c_master_recv(st->i2c, st->rx, 2);
+	if (ret)
+		goto out;
+
+	*val = (st->rx[0] << 8) | st->rx[1];
+out:
+	mutex_unlock(&st->buf_lock);
+	return ret;
+}
+
+static int ade7854_i2c_read_reg_24(struct device *dev,
+		u16 reg_address,
+		u32 *val)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	int ret;
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = (reg_address >> 8) & 0xFF;
+	st->tx[1] = reg_address & 0xFF;
+
+	ret = i2c_master_send(st->i2c, st->tx, 2);
+	if (ret)
+		goto out;
+
+	ret = i2c_master_recv(st->i2c, st->rx, 3);
+	if (ret)
+		goto out;
+
+	*val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
+out:
+	mutex_unlock(&st->buf_lock);
+	return ret;
+}
+
+static int ade7854_i2c_read_reg_32(struct device *dev,
+		u16 reg_address,
+		u32 *val)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	int ret;
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = (reg_address >> 8) & 0xFF;
+	st->tx[1] = reg_address & 0xFF;
+
+	ret = i2c_master_send(st->i2c, st->tx, 2);
+	if (ret)
+		goto out;
+
+	ret = i2c_master_recv(st->i2c, st->rx, 3);
+	if (ret)
+		goto out;
+
+	*val = (st->rx[0] << 24) | (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3];
+out:
+	mutex_unlock(&st->buf_lock);
+	return ret;
+}
+
+static int __devinit ade7854_i2c_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	int ret;
+	struct ade7854_state *st = kzalloc(sizeof *st, GFP_KERNEL);
+	if (!st) {
+		ret =  -ENOMEM;
+		return ret;
+	}
+
+	i2c_set_clientdata(client, st);
+	st->read_reg_8 = ade7854_i2c_read_reg_8;
+	st->read_reg_16 = ade7854_i2c_read_reg_16;
+	st->read_reg_24 = ade7854_i2c_read_reg_24;
+	st->read_reg_32 = ade7854_i2c_read_reg_32;
+	st->write_reg_8 = ade7854_i2c_write_reg_8;
+	st->write_reg_16 = ade7854_i2c_write_reg_16;
+	st->write_reg_24 = ade7854_i2c_write_reg_24;
+	st->write_reg_32 = ade7854_i2c_write_reg_32;
+	st->i2c = client;
+	st->irq = client->irq;
+
+	ret = ade7854_probe(st, &client->dev);
+	if (ret) {
+		kfree(st);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int __devexit ade7854_i2c_remove(struct i2c_client *client)
+{
+	return ade7854_remove(i2c_get_clientdata(client));
+}
+
+static const struct i2c_device_id ade7854_id[] = {
+	{ "ade7854", 0 },
+	{ "ade7858", 0 },
+	{ "ade7868", 0 },
+	{ "ade7878", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ade7854_id);
+
+static struct i2c_driver ade7854_i2c_driver = {
+	.driver = {
+		.name = "ade7854",
+	},
+	.probe    = ade7854_i2c_probe,
+	.remove   = __devexit_p(ade7854_i2c_remove),
+	.id_table = ade7854_id,
+};
+
+static __init int ade7854_i2c_init(void)
+{
+	return i2c_add_driver(&ade7854_i2c_driver);
+}
+module_init(ade7854_i2c_init);
+
+static __exit void ade7854_i2c_exit(void)
+{
+	i2c_del_driver(&ade7854_i2c_driver);
+}
+module_exit(ade7854_i2c_exit);
+
+
+MODULE_AUTHOR("Barry Song <[email protected]>");
+MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC I2C Driver");
+MODULE_LICENSE("GPL v2");

Added: trunk/drivers/staging/iio/meter/ade7854-spi.c (0 => 8585)


--- trunk/drivers/staging/iio/meter/ade7854-spi.c	                        (rev 0)
+++ trunk/drivers/staging/iio/meter/ade7854-spi.c	2010-04-01 05:56:52 UTC (rev 8585)
@@ -0,0 +1,359 @@
+/*
+ * ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver (SPI Bus)
+ *
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+
+#include "../iio.h"
+#include "ade7854.h"
+
+static int ade7854_spi_write_reg_8(struct device *dev,
+		u16 reg_address,
+		u8 value)
+{
+	int ret;
+	struct spi_message msg;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = st->tx,
+			.bits_per_word = 8,
+			.len = 4,
+		}
+	};
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = ADE7854_WRITE_REG;
+	st->tx[1] = (reg_address >> 8) & 0xFF;
+	st->tx[2] = reg_address & 0xFF;
+	st->tx[3] = value & 0xFF;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(xfers, &msg);
+	ret = spi_sync(st->spi, &msg);
+	mutex_unlock(&st->buf_lock);
+
+	return ret;
+}
+
+static int ade7854_spi_write_reg_16(struct device *dev,
+		u16 reg_address,
+		u16 value)
+{
+	int ret;
+	struct spi_message msg;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = st->tx,
+			.bits_per_word = 8,
+			.len = 5,
+		}
+	};
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = ADE7854_WRITE_REG;
+	st->tx[1] = (reg_address >> 8) & 0xFF;
+	st->tx[2] = reg_address & 0xFF;
+	st->tx[3] = (value >> 8) & 0xFF;
+	st->tx[4] = value & 0xFF;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(xfers, &msg);
+	ret = spi_sync(st->spi, &msg);
+	mutex_unlock(&st->buf_lock);
+
+	return ret;
+}
+
+static int ade7854_spi_write_reg_24(struct device *dev,
+		u16 reg_address,
+		u32 value)
+{
+	int ret;
+	struct spi_message msg;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = st->tx,
+			.bits_per_word = 8,
+			.len = 6,
+		}
+	};
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = ADE7854_WRITE_REG;
+	st->tx[1] = (reg_address >> 8) & 0xFF;
+	st->tx[2] = reg_address & 0xFF;
+	st->tx[3] = (value >> 16) & 0xFF;
+	st->tx[4] = (value >> 8) & 0xFF;
+	st->tx[5] = value & 0xFF;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(xfers, &msg);
+	ret = spi_sync(st->spi, &msg);
+	mutex_unlock(&st->buf_lock);
+
+	return ret;
+}
+
+static int ade7854_spi_write_reg_32(struct device *dev,
+		u16 reg_address,
+		u32 value)
+{
+	int ret;
+	struct spi_message msg;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = st->tx,
+			.bits_per_word = 8,
+			.len = 7,
+		}
+	};
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = ADE7854_WRITE_REG;
+	st->tx[1] = (reg_address >> 8) & 0xFF;
+	st->tx[2] = reg_address & 0xFF;
+	st->tx[3] = (value >> 24) & 0xFF;
+	st->tx[4] = (value >> 16) & 0xFF;
+	st->tx[5] = (value >> 8) & 0xFF;
+	st->tx[6] = value & 0xFF;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(xfers, &msg);
+	ret = spi_sync(st->spi, &msg);
+	mutex_unlock(&st->buf_lock);
+
+	return ret;
+}
+
+static int ade7854_spi_read_reg_8(struct device *dev,
+		u16 reg_address,
+		u8 *val)
+{
+	struct spi_message msg;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	int ret;
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = st->tx,
+			.bits_per_word = 8,
+			.len = 4,
+		},
+	};
+
+	mutex_lock(&st->buf_lock);
+
+	st->tx[0] = ADE7854_READ_REG;
+	st->tx[1] = (reg_address >> 8) & 0xFF;
+	st->tx[2] = reg_address & 0xFF;
+	st->tx[3] = 0;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(xfers, &msg);
+	ret = spi_sync(st->spi, &msg);
+	if (ret) {
+		dev_err(&st->spi->dev, "problem when reading 8 bit register 0x%02X",
+				reg_address);
+		goto error_ret;
+	}
+	*val = st->rx[3];
+
+error_ret:
+	mutex_unlock(&st->buf_lock);
+	return ret;
+}
+
+static int ade7854_spi_read_reg_16(struct device *dev,
+		u16 reg_address,
+		u16 *val)
+{
+	struct spi_message msg;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	int ret;
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = st->tx,
+			.bits_per_word = 8,
+			.len = 5,
+		},
+	};
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = ADE7854_READ_REG;
+	st->tx[1] = (reg_address >> 8) & 0xFF;
+	st->tx[2] = reg_address & 0xFF;
+	st->tx[3] = 0;
+	st->tx[4] = 0;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(xfers, &msg);
+	ret = spi_sync(st->spi, &msg);
+	if (ret) {
+		dev_err(&st->spi->dev, "problem when reading 16 bit register 0x%02X",
+				reg_address);
+		goto error_ret;
+	}
+	*val = (st->rx[3] << 8) | st->rx[4];
+
+error_ret:
+	mutex_unlock(&st->buf_lock);
+	return ret;
+}
+
+static int ade7854_spi_read_reg_24(struct device *dev,
+		u16 reg_address,
+		u32 *val)
+{
+	struct spi_message msg;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	int ret;
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = st->tx,
+			.bits_per_word = 8,
+			.len = 6,
+		},
+	};
+
+	mutex_lock(&st->buf_lock);
+
+	st->tx[0] = ADE7854_READ_REG;
+	st->tx[1] = (reg_address >> 8) & 0xFF;
+	st->tx[2] = reg_address & 0xFF;
+	st->tx[3] = 0;
+	st->tx[4] = 0;
+	st->tx[5] = 0;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(xfers, &msg);
+	ret = spi_sync(st->spi, &msg);
+	if (ret) {
+		dev_err(&st->spi->dev, "problem when reading 24 bit register 0x%02X",
+				reg_address);
+		goto error_ret;
+	}
+	*val = (st->rx[3] << 16) | (st->rx[4] << 8) | st->rx[5];
+
+error_ret:
+	mutex_unlock(&st->buf_lock);
+	return ret;
+}
+
+static int ade7854_spi_read_reg_32(struct device *dev,
+		u16 reg_address,
+		u32 *val)
+{
+	struct spi_message msg;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	int ret;
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = st->tx,
+			.bits_per_word = 8,
+			.len = 7,
+		},
+	};
+
+	mutex_lock(&st->buf_lock);
+
+	st->tx[0] = ADE7854_READ_REG;
+	st->tx[1] = (reg_address >> 8) & 0xFF;
+	st->tx[2] = reg_address & 0xFF;
+	st->tx[3] = 0;
+	st->tx[4] = 0;
+	st->tx[5] = 0;
+	st->tx[6] = 0;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(xfers, &msg);
+	ret = spi_sync(st->spi, &msg);
+	if (ret) {
+		dev_err(&st->spi->dev, "problem when reading 32 bit register 0x%02X",
+				reg_address);
+		goto error_ret;
+	}
+	*val = (st->rx[3] << 24) | (st->rx[4] << 16) | (st->rx[5] << 8) | st->rx[6];
+
+error_ret:
+	mutex_unlock(&st->buf_lock);
+	return ret;
+}
+
+static int __devinit ade7854_spi_probe(struct spi_device *spi)
+{
+	int ret;
+	struct ade7854_state *st = kzalloc(sizeof *st, GFP_KERNEL);
+	if (!st) {
+		ret =  -ENOMEM;
+		return ret;
+	}
+
+	spi_set_drvdata(spi, st);
+	st->read_reg_8 = ade7854_spi_read_reg_8;
+	st->read_reg_16 = ade7854_spi_read_reg_16;
+	st->read_reg_24 = ade7854_spi_read_reg_24;
+	st->read_reg_32 = ade7854_spi_read_reg_32;
+	st->write_reg_8 = ade7854_spi_write_reg_8;
+	st->write_reg_16 = ade7854_spi_write_reg_16;
+	st->write_reg_24 = ade7854_spi_write_reg_24;
+	st->write_reg_32 = ade7854_spi_write_reg_32;
+	st->irq = spi->irq;
+	st->spi = spi;
+
+	ret = ade7854_probe(st, &spi->dev);
+	if (ret) {
+		kfree(st);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ade7854_spi_remove(struct spi_device *spi)
+{
+	ade7854_remove(spi_get_drvdata(spi));
+
+	return 0;
+}
+
+static struct spi_driver ade7854_driver = {
+	.driver = {
+		.name = "ade7854",
+		.owner = THIS_MODULE,
+	},
+	.probe = ade7854_spi_probe,
+	.remove = __devexit_p(ade7854_spi_remove),
+};
+
+static __init int ade7854_init(void)
+{
+	return spi_register_driver(&ade7854_driver);
+}
+module_init(ade7854_init);
+
+static __exit void ade7854_exit(void)
+{
+	spi_unregister_driver(&ade7854_driver);
+}
+module_exit(ade7854_exit);
+
+MODULE_AUTHOR("Barry Song <[email protected]>");
+MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC SPI Driver");
+MODULE_LICENSE("GPL v2");

Modified: trunk/drivers/staging/iio/meter/ade7854.c (8584 => 8585)


--- trunk/drivers/staging/iio/meter/ade7854.c	2010-04-01 05:44:55 UTC (rev 8584)
+++ trunk/drivers/staging/iio/meter/ade7854.c	2010-04-01 05:56:52 UTC (rev 8585)
@@ -13,7 +13,6 @@
 #include <linux/mutex.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
-#include <linux/spi/spi.h>
 
 #include <linux/sysfs.h>
 #include <linux/list.h>
@@ -23,298 +22,17 @@
 #include "meter.h"
 #include "ade7854.h"
 
-static int ade7854_spi_write_reg_8(struct device *dev,
-		u16 reg_address,
-		u8 value)
-{
-	int ret;
-	struct spi_message msg;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 4,
-		}
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADE7854_WRITE_REG;
-	st->tx[1] = (reg_address >> 8) & 0xFF;
-	st->tx[2] = reg_address & 0xFF;
-	st->tx[3] = 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 ade7854_spi_write_reg_16(struct device *dev,
-		u16 reg_address,
-		u16 value)
-{
-	int ret;
-	struct spi_message msg;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 5,
-		}
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADE7854_WRITE_REG;
-	st->tx[1] = (reg_address >> 8) & 0xFF;
-	st->tx[2] = reg_address & 0xFF;
-	st->tx[3] = (value >> 8) & 0xFF;
-	st->tx[4] = 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 ade7854_spi_write_reg_24(struct device *dev,
-		u16 reg_address,
-		u32 value)
-{
-	int ret;
-	struct spi_message msg;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 6,
-		}
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADE7854_WRITE_REG;
-	st->tx[1] = (reg_address >> 8) & 0xFF;
-	st->tx[2] = reg_address & 0xFF;
-	st->tx[3] = (value >> 16) & 0xFF;
-	st->tx[4] = (value >> 8) & 0xFF;
-	st->tx[5] = 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 ade7854_spi_write_reg_32(struct device *dev,
-		u16 reg_address,
-		u32 value)
-{
-	int ret;
-	struct spi_message msg;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 7,
-		}
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADE7854_WRITE_REG;
-	st->tx[1] = (reg_address >> 8) & 0xFF;
-	st->tx[2] = reg_address & 0xFF;
-	st->tx[3] = (value >> 24) & 0xFF;
-	st->tx[4] = (value >> 16) & 0xFF;
-	st->tx[5] = (value >> 8) & 0xFF;
-	st->tx[6] = 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 ade7854_spi_read_reg_8(struct device *dev,
-		u16 reg_address,
-		u8 *val)
-{
-	struct spi_message msg;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
-	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 4,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-
-	st->tx[0] = ADE7854_READ_REG;
-	st->tx[1] = (reg_address >> 8) & 0xFF;
-	st->tx[2] = reg_address & 0xFF;
-	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 8 bit register 0x%02X",
-				reg_address);
-		goto error_ret;
-	}
-	*val = st->rx[3];
-
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
-}
-
-static int ade7854_spi_read_reg_16(struct device *dev,
-		u16 reg_address,
-		u16 *val)
-{
-	struct spi_message msg;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
-	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 5,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADE7854_READ_REG;
-	st->tx[1] = (reg_address >> 8) & 0xFF;
-	st->tx[2] = reg_address & 0xFF;
-	st->tx[3] = 0;
-	st->tx[4] = 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[3] << 8) | st->rx[4];
-
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
-}
-
-static int ade7854_spi_read_reg_24(struct device *dev,
-		u16 reg_address,
-		u32 *val)
-{
-	struct spi_message msg;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
-	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 6,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-
-	st->tx[0] = ADE7854_READ_REG;
-	st->tx[1] = (reg_address >> 8) & 0xFF;
-	st->tx[2] = reg_address & 0xFF;
-	st->tx[3] = 0;
-	st->tx[4] = 0;
-	st->tx[5] = 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[3] << 16) | (st->rx[4] << 8) | st->rx[5];
-
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
-}
-
-static int ade7854_spi_read_reg_32(struct device *dev,
-		u16 reg_address,
-		u32 *val)
-{
-	struct spi_message msg;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
-	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 4,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-
-	st->tx[0] = ADE7854_READ_REG;
-	st->tx[1] = (reg_address >> 8) & 0xFF;
-	st->tx[2] = reg_address & 0xFF;
-	st->tx[3] = 0;
-	st->tx[4] = 0;
-	st->tx[5] = 0;
-	st->tx[6] = 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 32 bit register 0x%02X",
-				reg_address);
-		goto error_ret;
-	}
-	*val = (st->rx[3] << 24) | (st->rx[4] << 16) | (st->rx[5] << 8) | st->rx[6];
-
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
-}
-
 static ssize_t ade7854_read_8bit(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
 	int ret;
 	u8 val = 0;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
-	ret = ade7854_spi_read_reg_8(dev, this_attr->address, &val);
+	ret = st->read_reg_8(dev, this_attr->address, &val);
 	if (ret)
 		return ret;
 
@@ -327,9 +45,11 @@
 {
 	int ret;
 	u16 val = 0;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
-	ret = ade7854_spi_read_reg_16(dev, this_attr->address, &val);
+	ret = st->read_reg_16(dev, this_attr->address, &val);
 	if (ret)
 		return ret;
 
@@ -342,9 +62,11 @@
 {
 	int ret;
 	u32 val = 0;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
-	ret = ade7854_spi_read_reg_24(dev, this_attr->address, &val);
+	ret = st->read_reg_24(dev, this_attr->address, &val);
 	if (ret)
 		return ret;
 
@@ -358,8 +80,10 @@
 	int ret;
 	u32 val = 0;
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
 
-	ret = ade7854_spi_read_reg_32(dev, this_attr->address, &val);
+	ret = st->read_reg_32(dev, this_attr->address, &val);
 	if (ret)
 		return ret;
 
@@ -372,13 +96,16 @@
 		size_t len)
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+
 	int ret;
 	long val;
 
 	ret = strict_strtol(buf, 10, &val);
 	if (ret)
 		goto error_ret;
-	ret = ade7854_spi_write_reg_8(dev, this_attr->address, val);
+	ret = st->write_reg_8(dev, this_attr->address, val);
 
 error_ret:
 	return ret ? ret : len;
@@ -390,13 +117,16 @@
 		size_t len)
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+
 	int ret;
 	long val;
 
 	ret = strict_strtol(buf, 10, &val);
 	if (ret)
 		goto error_ret;
-	ret = ade7854_spi_write_reg_16(dev, this_attr->address, val);
+	ret = st->write_reg_16(dev, this_attr->address, val);
 
 error_ret:
 	return ret ? ret : len;
@@ -408,13 +138,16 @@
 		size_t len)
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+
 	int ret;
 	long val;
 
 	ret = strict_strtol(buf, 10, &val);
 	if (ret)
 		goto error_ret;
-	ret = ade7854_spi_write_reg_24(dev, this_attr->address, val);
+	ret = st->write_reg_24(dev, this_attr->address, val);
 
 error_ret:
 	return ret ? ret : len;
@@ -426,13 +159,16 @@
 		size_t len)
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+
 	int ret;
 	long val;
 
 	ret = strict_strtol(buf, 10, &val);
 	if (ret)
 		goto error_ret;
-	ret = ade7854_spi_write_reg_32(dev, this_attr->address, val);
+	ret = st->write_reg_32(dev, this_attr->address, val);
 
 error_ret:
 	return ret ? ret : len;
@@ -440,16 +176,15 @@
 
 static int ade7854_reset(struct device *dev)
 {
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+
 	int ret;
 	u16 val;
 
-	ade7854_spi_read_reg_16(dev,
-			ADE7854_CONFIG,
-			&val);
+	st->read_reg_16(dev, ADE7854_CONFIG, &val);
 	val |= 1 << 7; /* Software Chip Reset */
-	ret = ade7854_spi_write_reg_16(dev,
-			ADE7854_CONFIG,
-			val);
+	ret = st->write_reg_16(dev, ADE7854_CONFIG, val);
 
 	return ret;
 }
@@ -693,9 +428,13 @@
 
 static int ade7854_set_irq(struct device *dev, bool enable)
 {
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+
 	int ret;
 	u32 irqen;
-	ret = ade7854_spi_read_reg_32(dev, ADE7854_MASK0, &irqen);
+
+	ret = st->read_reg_32(dev, ADE7854_MASK0, &irqen);
 	if (ret)
 		goto error_ret;
 
@@ -705,7 +444,7 @@
 	else
 		irqen &= ~(1 << 17);
 
-	ret = ade7854_spi_write_reg_32(dev, ADE7854_MASK0, irqen);
+	ret = st->write_reg_32(dev, ADE7854_MASK0, irqen);
 	if (ret)
 		goto error_ret;
 
@@ -718,10 +457,6 @@
 	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 = ade7854_set_irq(dev, false);
 	if (ret) {
@@ -828,16 +563,9 @@
 	.attrs = ade7854_attributes,
 };
 
-static int __devinit ade7854_probe(struct spi_device *spi)
+int ade7854_probe(struct ade7854_state *st, struct device *dev)
 {
 	int ret, regdone = 0;
-	struct ade7854_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)*ADE7854_MAX_RX, GFP_KERNEL);
@@ -850,7 +578,6 @@
 		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();
@@ -859,7 +586,7 @@
 		goto error_free_tx;
 	}
 
-	st->indio_dev->dev.parent = &spi->dev;
+	st->indio_dev->dev.parent = dev;
 	st->indio_dev->num_interrupt_lines = 1;
 	st->indio_dev->event_attrs = &ade7854_event_attribute_group;
 	st->indio_dev->attrs = &ade7854_attribute_group;
@@ -882,7 +609,7 @@
 		goto error_unreg_ring_funcs;
 	}
 
-	if (spi->irq) {
+	if (st->irq) {
 #if 0 /* fixme: here we should support */
 		iio_init_work_cont(&st->work_cont_thresh,
 				NULL,
@@ -891,7 +618,7 @@
 				0,
 				st);
 #endif
-		ret = iio_register_interrupt_line(spi->irq,
+		ret = iio_register_interrupt_line(st->irq,
 				st->indio_dev,
 				0,
 				IRQF_TRIGGER_FALLING,
@@ -903,12 +630,10 @@
 		if (ret)
 			goto error_unregister_line;
 	}
-
 	/* Get the device into a sane initial state */
 	ret = ade7854_initial_setup(st);
 	if (ret)
 		goto error_remove_trigger;
-	return 0;
 
 error_remove_trigger:
 	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
@@ -931,20 +656,19 @@
 	kfree(st->rx);
 error_free_st:
 	kfree(st);
-error_ret:
 	return ret;
+
 }
+EXPORT_SYMBOL(ade7854_probe);
 
-/* fixme, confirm ordering in this function */
-static int ade7854_remove(struct spi_device *spi)
+int ade7854_remove(struct ade7854_state *st)
 {
-	struct ade7854_state *st = spi_get_drvdata(spi);
 	struct iio_dev *indio_dev = st->indio_dev;
 
 	flush_scheduled_work();
 
 	ade7854_remove_trigger(indio_dev);
-	if (spi->irq)
+	if (st->irq)
 		iio_unregister_interrupt_line(indio_dev, 0);
 
 	ade7854_uninitialize_ring(indio_dev->ring);
@@ -956,28 +680,8 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(ade7854_remove);
 
-static struct spi_driver ade7854_driver = {
-	.driver = {
-		.name = "ade7854",
-		.owner = THIS_MODULE,
-	},
-	.probe = ade7854_probe,
-	.remove = __devexit_p(ade7854_remove),
-};
-
-static __init int ade7854_init(void)
-{
-	return spi_register_driver(&ade7854_driver);
-}
-module_init(ade7854_init);
-
-static __exit void ade7854_exit(void)
-{
-	spi_unregister_driver(&ade7854_driver);
-}
-module_exit(ade7854_exit);
-
 MODULE_AUTHOR("Barry Song <[email protected]>");
 MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver");
 MODULE_LICENSE("GPL v2");

Modified: trunk/drivers/staging/iio/meter/ade7854.h (8584 => 8585)


--- trunk/drivers/staging/iio/meter/ade7854.h	2010-04-01 05:44:55 UTC (rev 8584)
+++ trunk/drivers/staging/iio/meter/ade7854.h	2010-04-01 05:56:52 UTC (rev 8585)
@@ -146,7 +146,7 @@
 
 /**
  * struct ade7854_state - device instance specific data
- * @us:			actual spi_device
+ * @spi:			actual spi_device
  * @work_trigger_to_ring: bh for triggered event handling
  * @work_cont_thresh: CLEAN
  * @inter:		used to check if new interrupt has been triggered
@@ -158,7 +158,8 @@
  * @buf_lock:		mutex to protect tx and rx
  **/
 struct ade7854_state {
-	struct spi_device		*us;
+	struct spi_device		*spi;
+	struct i2c_client               *i2c;
 	struct work_struct		work_trigger_to_ring;
 	struct iio_work_cont		work_cont_thresh;
 	s64				last_timestamp;
@@ -166,8 +167,21 @@
 	struct iio_trigger		*trig;
 	u8				*tx;
 	u8				*rx;
+	int				(*read_reg_8) (struct device *, u16, u8 *);
+	int				(*read_reg_16) (struct device *, u16, u16 *);
+	int				(*read_reg_24) (struct device *, u16, u32 *);
+	int				(*read_reg_32) (struct device *, u16, u32 *);
+	int				(*write_reg_8) (struct device *, u16, u8);
+	int				(*write_reg_16) (struct device *, u16, u16);
+	int				(*write_reg_24) (struct device *, u16, u32);
+	int				(*write_reg_32) (struct device *, u16, u32);
+	int                             irq;
 	struct mutex			buf_lock;
 };
+
+extern int ade7854_probe(struct ade7854_state *st, struct device *dev);
+extern int ade7854_remove(struct ade7854_state *st);
+
 #ifdef CONFIG_IIO_RING_BUFFER
 /* At the moment triggers are only used for ring buffer
  * filling. This may change!
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to