[PATCH 1/2] staging:iio:adc: as1531 driver initial conversion from hwmon submission.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Fabien Marteau <fabien.marteau@xxxxxxxxxxxx>

V2: Fix double mutex unlock and whitespace (Guenter Roeck).
Signed-off-by: Jonathan Cameron <jic23@xxxxxxxxx>
---
 drivers/staging/iio/adc/Kconfig  |   10 ++
 drivers/staging/iio/adc/Makefile |    2 +
 drivers/staging/iio/adc/as1531.c |  209 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 221 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 8c751c4..4af730a 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -168,6 +168,16 @@ config ADT7410
 	  Say yes here to build support for Analog Devices ADT7410
 	  temperature sensors.
 
+config AS1531
+tristate "Austria Microsystems AS1531 Analog to Digital Converter"
+	depends on SPI_MASTER
+	help
+	  If you say yes here you get support for Austria Microsystems AS1531.
+		AS1531 is a 12Âbits Analog to digitals converter with 8 channels
+		provided by Austria-Microsystems company.
+	  This driver can also be built as a module.  If so, the module
+	  will be called as1531.
+
 config MAX1363
 	tristate "Maxim max1363 ADC driver"
 	depends on I2C
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index 1d9b3f5..027b94e2 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -39,3 +39,5 @@ obj-$(CONFIG_AD7816) += ad7816.o
 obj-$(CONFIG_ADT75) += adt75.o
 obj-$(CONFIG_ADT7310) += adt7310.o
 obj-$(CONFIG_ADT7410) += adt7410.o
+
+obj-$(CONFIG_AS1531) += as1531.o
\ No newline at end of file
diff --git a/drivers/staging/iio/adc/as1531.c b/drivers/staging/iio/adc/as1531.c
new file mode 100644
index 0000000..1724c39
--- /dev/null
+++ b/drivers/staging/iio/adc/as1531.c
@@ -0,0 +1,209 @@
+/*
+ * as1531.c
+ *
+ * Driver for Austria-Microsystem Analog to Digital Converter.
+ *
+ * Copyright (c) 2010, 2011 Fabien Marteau <fabien.marteau@xxxxxxxxxxxx>
+ * Driver based on Marc Pignat <marc.pignat@xxxxxxx> adcxx.c driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "adc.h"
+
+#define AS1531_SPI_SPEED 64941
+#define AS1531_MAX_VALUE 2500
+
+#define AS1531_START_BIT	(0x80)
+#define AS1531_CHAN0		(0<<4)
+#define AS1531_CHAN1		(4<<4)
+#define AS1531_CHAN2		(1<<4)
+#define AS1531_CHAN3		(5<<4)
+#define AS1531_CHAN4		(2<<4)
+#define AS1531_CHAN5		(6<<4)
+#define AS1531_CHAN6		(3<<4)
+#define AS1531_CHAN7		(7<<4)
+
+#define AS1531_RANGE_0_TO_VREF			(1<<3)
+#define AS1531_RANGE_HALFVREF_TO_HALFVREF	(0<<3)
+
+#define AS1531_MODE_COM		(1<<2)
+#define AS1531_MODE_DIFF	(0<<2)
+
+#define AS1531_POWER_DOWN		0x0
+#define AS1531_POWER_REDUCED		0x1
+#define AS1531_POWER_REDUCED_BIS	0x2
+#define AS1531_POWER_NORMAL		0x3
+
+struct as1531_state {
+	struct spi_device *spi;
+	struct mutex lock;
+};
+
+static int as1531_message(struct spi_device *spi, int cmd, int *ret_value)
+{
+	struct spi_message	message;
+	struct spi_transfer	x[1];
+	int status, i;
+	u8	cmd_send;
+	unsigned char buf[64];
+	unsigned char buf_read[64];
+
+	cmd_send = cmd;
+
+	spi_message_init(&message);
+	memset(x, 0, sizeof x);
+	memset(buf, 0, sizeof(buf));
+	memset(buf_read, 0, sizeof(buf_read));
+
+	for (i = 0; i < 8; i++) {
+		buf[i] = ((cmd_send & 0x80)>>7);
+		cmd_send = cmd_send << 1;
+	}
+
+	x[0].tx_buf = buf;
+	x[0].len = 24;
+	x[0].rx_buf = buf_read;
+	x[0].speed_hz = AS1531_SPI_SPEED;
+	x[0].bits_per_word = 1;
+	spi_message_add_tail(&x[0], &message);
+
+	status = spi_sync(spi, &message);
+	if (status < 0)
+		return status;
+
+	*ret_value = buf_read[11] & 0x01;
+	for (i = 12; i < 23 ; i++) {
+		*ret_value = *ret_value << 1;
+		*ret_value = *ret_value | (buf_read[i]&0x01);
+	}
+
+	return 0;
+}
+
+static int as1531_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val,
+			   int *val2,
+			   long m)
+{
+	int status = 0;
+	int ret_value = 0;
+	struct as1531_state *st = iio_priv(indio_dev);
+
+	if (mutex_lock_interruptible(&st->lock))
+		return -ERESTARTSYS;
+
+	status = as1531_message(st->spi,
+				AS1531_START_BIT | chan->address |
+				AS1531_RANGE_0_TO_VREF | AS1531_MODE_COM |
+				AS1531_POWER_NORMAL,
+				&ret_value);
+	mutex_unlock(&st->lock);
+	if (status < 0)
+		return status;
+
+	*val = ret_value*2500/4096;
+
+	return IIO_VAL_INT;
+}
+
+static const struct iio_chan_spec as1531_channels[] = {
+	IIO_CHAN(IIO_IN, 0, 1, 1, NULL, 0, 1, 0, AS1531_CHAN0, 0, {}, 0),
+	IIO_CHAN(IIO_IN, 0, 1, 1, NULL, 1, 1, 0, AS1531_CHAN1, 1, {}, 0),
+	IIO_CHAN(IIO_IN, 0, 1, 1, NULL, 2, 1, 0, AS1531_CHAN2, 2, {}, 0),
+	IIO_CHAN(IIO_IN, 0, 1, 1, NULL, 3, 1, 0, AS1531_CHAN3, 3, {}, 0),
+	IIO_CHAN(IIO_IN, 0, 1, 1, NULL, 4, 1, 0, AS1531_CHAN4, 4, {}, 0),
+	IIO_CHAN(IIO_IN, 0, 1, 1, NULL, 5, 1, 0, AS1531_CHAN5, 5, {}, 0),
+	IIO_CHAN(IIO_IN, 0, 1, 1, NULL, 6, 1, 0, AS1531_CHAN6, 6, {}, 0),
+	IIO_CHAN(IIO_IN, 0, 1, 1, NULL, 7, 1, 0, AS1531_CHAN7, 7, {}, 0),
+};
+
+static const struct iio_info as1531_info = {
+	.read_raw = &as1531_read_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int __devinit as1531_probe(struct spi_device *spi)
+{
+	int ret;
+	struct as1531_state *st;
+	struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
+
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
+	st = iio_priv(indio_dev);
+	mutex_init(&st->lock);
+	st->spi = spi;
+
+	spi_set_drvdata(spi, indio_dev);
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->info = &as1531_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = as1531_channels;
+	indio_dev->num_channels = ARRAY_SIZE(as1531_channels);
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0)
+		iio_free_device(indio_dev);
+	return ret;
+}
+
+static int as1531_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+
+	iio_device_unregister(indio_dev);
+	return 0;
+}
+
+static const struct spi_device_id as1531_id[] = {
+	{"as1531", 0},
+	{}
+};
+
+static struct spi_driver as1531_driver = {
+	.driver = {
+		.name	= "as1531",
+		.owner	= THIS_MODULE,
+	},
+	.probe	= as1531_probe,
+	.remove	= __devexit_p(as1531_remove),
+	.id_table = as1531_id,
+};
+
+static int __init init_as1531(void)
+{
+	return spi_register_driver(&as1531_driver);
+}
+module_init(init_as1531);
+
+static void __exit exit_as1531(void)
+{
+	spi_unregister_driver(&as1531_driver);
+}
+module_exit(exit_as1531);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Fabien Marteau <fabien.marteau@xxxxxxxxxxxx>");
+MODULE_DESCRIPTION("Driver for AS1531 ADC");
-- 
1.7.3.4


_______________________________________________
lm-sensors mailing list
lm-sensors@xxxxxxxxxxxxxx
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors



[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux