[PATCH] Staging: adis16255: some TODO issues solved

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

 



This patch solves some issues mentioned in TODO list:
- sample rate exported to sysfs
- spi_adis16255_bringup and spi_adis16255_shutdown encapsulated
- chip selftest in spi_adis16255_bringup
- kernel messages reduced to a reasonable number


Signed-off-by: Matthias Brugger <mensch0815@xxxxxxxxx>
---
 drivers/staging/Kconfig               |    2 +
 drivers/staging/Makefile              |    1 +
 drivers/staging/adis16255/Kconfig     |   10 +-
 drivers/staging/adis16255/Makefile    |    2 +-
 drivers/staging/adis16255/TODO        |    5 -
 drivers/staging/adis16255/adis16255.c |  206 +++++++++++++++++++++------------
 6 files changed, 144 insertions(+), 82 deletions(-)

diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 7696a66..2670b6c 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -139,5 +139,7 @@ source "drivers/staging/dt3155/Kconfig"

 source "drivers/staging/crystalhd/Kconfig"

+source "drivers/staging/adis16255/Kconfig"
+
 endif # !STAGING_EXCLUDE_BUILD
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index ea2e70e..fd49d83 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -51,3 +51,4 @@ obj-$(CONFIG_PCMCIA_NETWAVE)	+= netwave/
 obj-$(CONFIG_FB_SM7XX)		+= sm7xx/
 obj-$(CONFIG_DT3155)		+= dt3155/
 obj-$(CONFIG_CRYSTALHD)		+= crystalhd/
+obj-$(CONFIG_ADIS16255)		+= adis16255/
diff --git a/drivers/staging/adis16255/Kconfig
b/drivers/staging/adis16255/Kconfig
index 3952cf9..a642be6 100644
--- a/drivers/staging/adis16255/Kconfig
+++ b/drivers/staging/adis16255/Kconfig
@@ -2,8 +2,10 @@ config ADIS16255
 	tristate "Ananlog Devices ADIS16250/16255"
 	depends on SPI && SYSFS
 	---help---
-      If you say yes here you get support for the Analog Devices
-      ADIS16250/16255 Low Power Gyroscope.
+	If you say yes here you get support for the Analog Devices
+	ADIS16250/16255 Low Power Gyroscope. The driver exposes
+	orientation and gyroscope value, as well as sample rate
+	to the sysfs.

-      This driver can also be built as a module. If so, the module
-      will be called adis16255.
+	This driver can also be built as a module. If so, the module
+	will be called adis16255.
diff --git a/drivers/staging/adis16255/Makefile
b/drivers/staging/adis16255/Makefile
index 796dac4..8c39081 100644
--- a/drivers/staging/adis16255/Makefile
+++ b/drivers/staging/adis16255/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_ADIS16255) += adis16255.o
+obj-$(CONFIG_ADIS16255)		+= adis16255.o
diff --git a/drivers/staging/adis16255/TODO b/drivers/staging/adis16255/TODO
index 31e4ac3..ec60f31 100644
--- a/drivers/staging/adis16255/TODO
+++ b/drivers/staging/adis16255/TODO
@@ -1,8 +1,3 @@
-* sample rate changeable or at least readable from sysfs
 * reset gyroscope
-* encapsulate adis_init and adis_turn_off
-* AD_CHK deletion
-* chip selftest in adis_init
-* reduce kernel messages to reasonable amount

 Contact: Matthias Brugger <mensch0815@xxxxxxxxx>
diff --git a/drivers/staging/adis16255/adis16255.c
b/drivers/staging/adis16255/adis16255.c
index 9a8ced1..1ba11f0 100644
--- a/drivers/staging/adis16255/adis16255.c
+++ b/drivers/staging/adis16255/adis16255.c
@@ -21,6 +21,14 @@
  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */

+/*
+ * The driver just has a bare interface to the sysfs (sample rate in Hz,
+ * orientation (x, y, z) and gyroscope data in °/sec.
+ *
+ * It should be added to iio subsystem when this has left staging.
+ *
+ */
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/device.h>
@@ -69,7 +77,6 @@ struct spi_adis16255_data {
 	struct device dev;
 	struct spi_device *spi;
 	s16 data;
-	int irq_adis;
 	int irq;
 	u8 negative;
 	char direction;
@@ -87,7 +94,7 @@ static int spi_adis16255_read_data(struct
spi_adis16255_data *spiadis,
 	u8 *buf, *rx;
 	int ret;

-	buf = kmalloc(4, GFP_KERNEL);
+	buf = kzalloc(4, GFP_KERNEL);
 	if (buf == NULL)
 		return -ENOMEM;

@@ -98,9 +105,6 @@ static int spi_adis16255_read_data(struct
spi_adis16255_data *spiadis,
 	}

 	buf[0] = adr;
-	buf[1] = 0x00;
-	buf[2] = 0x00;
-	buf[3] = 0x00;

 	spi_message_init(&msg);
 	memset(&xfer1, 0, sizeof(xfer1));
@@ -176,7 +180,7 @@ static int spi_adis16255_write_data(struct
spi_adis16255_data *spiadis,

 	ret = spi_sync(spi, &msg);
 	if (ret != 0)
-		dev_warn(&spi->dev, "wirte data to %#x %#x failed\n",
+		dev_warn(&spi->dev, "write data to %#x %#x failed\n",
 				buf[0], buf[2]);

 	kfree(rx);
@@ -191,27 +195,29 @@ static irqreturn_t adis_irq_thread(int irq, void *dev_id)
 {
 	struct spi_adis16255_data *spiadis = dev_id;
 	int status;
-	u16 value;
+	u16 value = 0;

 	status =  spi_adis16255_read_data(spiadis, ADIS_GYRO_OUT, (u8 *)&value);
-	if (status == 0) {
-		/* perform on new data only... */
-		if (value & 0x8000) {
-			/* delete error and new data bit */
-			value = value & 0x3fff;
-			/* set negative value */
-			if (value & 0x2000)
-				value = value | 0xe000;
-
-			if (likely(spiadis->negative))
-				value = -value;
-
-			spiadis->data = (s16) value;
-		}
-	} else {
+	if (status != 0) {
 		dev_warn(&spiadis->spi->dev, "SPI FAILED\n");
+		goto exit;
 	}

+	/* perform on new data only... */
+	if (value & 0x8000) {
+		/* delete error and new data bit */
+		value = value & 0x3fff;
+		/* set negative value */
+		if (value & 0x2000)
+			value = value | 0xe000;
+
+		if (likely(spiadis->negative))
+			value = -value;
+
+		spiadis->data = (s16) value;
+	}
+
+exit:
 	return IRQ_HANDLED;
 }

@@ -235,9 +241,36 @@ ssize_t adis16255_show_direction(struct device *device,
 }
 DEVICE_ATTR(direction, S_IRUGO , adis16255_show_direction, NULL);

+ssize_t adis16255_show_sample_rate(struct device *device,
+		struct device_attribute *da,
+		char *buf)
+{
+	struct spi_adis16255_data *spiadis = dev_get_drvdata(device);
+	int status = 0;
+	u16 value = 0;
+	int ts = 0;
+
+	status = spi_adis16255_read_data(spiadis, ADIS_SMPL_PRD_MSB,
+				(u8 *)&value);
+	if (status != 0)
+		return -EINVAL;
+
+	if (value & 0x80) {
+		/* timebase = 60.54 ms */
+		ts = 60540 * ((0x7f & value) + 1);
+	} else {
+		/* timebase = 1.953 ms */
+		ts = 1953 * ((0x7f & value) + 1);
+	}
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", (1000*1000)/ts);
+}
+DEVICE_ATTR(sample_rate, S_IRUGO , adis16255_show_sample_rate, NULL);
+
 static struct attribute *adis16255_attributes[] = {
 	&dev_attr_data.attr,
 	&dev_attr_direction.attr,
+	&dev_attr_sample_rate.attr,
 	NULL
 };

@@ -260,43 +293,100 @@ static int spi_adis16255_shutdown(struct
spi_adis16255_data *spiadis)
 	return 0;
 }

+static int spi_adis16255_bringup(struct spi_adis16255_data *spiadis)
+{
+	int status = 0;
+	u16 value = 0;
+
+	status = spi_adis16255_read_data(spiadis, ADIS_GYRO_SCALE,
+				(u8 *)&value);
+	if (status != 0)
+		goto err;
+	if (value != 0x0800) {
+		dev_warn(&spiadis->spi->dev, "Scale factor is none default"
+				"value (%.4x)\n", value);
+	}
+
+	/* timebase = 1.953 ms, Ns = 0 -> 512 Hz sample rate */
+	value =  0x0001;
+	status = spi_adis16255_write_data(spiadis,
+				ADIS_SMPL_PRD_MSB, ADIS_SMPL_PRD_LSB,
+				(u8 *)&value);
+	if (status != 0)
+		goto err;
+
+	/* start internal self-test */
+	value = 0x0400;
+	status = spi_adis16255_write_data(spiadis,
+				ADIS_MSC_CTRL_MSB, ADIS_MSC_CTRL_LSB,
+				(u8 *)&value);
+	if (status != 0)
+		goto err;
+
+	/* wait 35 ms to finish self-test */
+	msleep(35);
+
+	value = 0x0000;
+	status = spi_adis16255_read_data(spiadis, ADIS_STATUS,
+				(u8 *)&value);
+	if (status != 0)
+		goto err;
+
+	if (value & 0x23) {
+		if (value & 0x20) {
+			dev_warn(&spiadis->spi->dev, "self-test error\n");
+			status = -ENODEV;
+			goto err;
+		} else if (value & 0x3)	{
+			dev_warn(&spiadis->spi->dev, "Sensor voltage"
+						"out of range.\n");
+			status = -ENODEV;
+			goto err;
+		}
+	}
+
+	/* set interrupt to active high on DIO0 when data ready */
+	value = 0x0006;
+	status = spi_adis16255_write_data(spiadis,
+				ADIS_MSC_CTRL_MSB, ADIS_MSC_CTRL_LSB,
+				(u8 *)&value);
+	if (status != 0)
+		goto err;
+	return status;
+
+err:
+	spi_adis16255_shutdown(spiadis);
+	return status;
+}
+
 /*-------------------------------------------------------------------------*/

 static int spi_adis16255_probe(struct spi_device *spi)
 {

-#define AD_CHK(_ss)\
-	do {\
-		status = _ss;\
-		if (status != 0)\
-			goto irq_err;\
-	} while (0);
-
 	struct adis16255_init_data *init_data = spi->dev.platform_data;
 	struct spi_adis16255_data  *spiadis;
 	int status = 0;
-	u16 value;

 	spiadis = kzalloc(sizeof(*spiadis), GFP_KERNEL);
 	if (!spiadis)
 		return -ENOMEM;

 	spiadis->spi = spi;
-	spiadis->irq_adis = init_data->irq;
 	spiadis->direction = init_data->direction;

 	if (init_data->negative)
 		spiadis->negative = 1;

-	status = gpio_request(spiadis->irq_adis, "adis16255");
+	status = gpio_request(init_data->irq, "adis16255");
 	if (status != 0)
 		goto err;

-	status = gpio_direction_input(spiadis->irq_adis);
+	status = gpio_direction_input(init_data->irq);
 	if (status != 0)
 		goto gpio_err;

-	spiadis->irq = gpio_to_irq(spiadis->irq_adis);
+	spiadis->irq = gpio_to_irq(init_data->irq);

 	status = request_threaded_irq(spiadis->irq,
 			NULL, adis_irq_thread,
@@ -307,50 +397,25 @@ static int spi_adis16255_probe(struct spi_device *spi)
 		goto gpio_err;
 	}

-	dev_dbg(&spi->dev, "GPIO %d IRQ %d\n", spiadis->irq_adis, spiadis->irq);
+	dev_dbg(&spi->dev, "GPIO %d IRQ %d\n", init_data->irq, spiadis->irq);

 	dev_set_drvdata(&spi->dev, spiadis);
-	AD_CHK(sysfs_create_group(&spi->dev.kobj, &adis16255_attr_group));
-
-	dev_info(&spi->dev, "spi_adis16255 driver added!\n");
-
-	AD_CHK(spi_adis16255_read_data(spiadis, ADIS_SUPPLY_OUT, (u8 *)&value));
-	dev_info(&spi->dev, "sensor works with %d mV (%.4x)!\n",
-			((value & 0x0fff)*18315)/10000,
-			(value & 0x0fff));
-
-	AD_CHK(spi_adis16255_read_data(spiadis, ADIS_GYRO_SCALE, (u8 *)&value));
-	dev_info(&spi->dev, "adis GYRO_SCALE is %.4x\n", value);
-
-	AD_CHK(spi_adis16255_read_data(spiadis, ADIS_STATUS, (u8 *)&value));
-	dev_info(&spi->dev, "adis STATUS is %.4x\n", value);
+	status = sysfs_create_group(&spi->dev.kobj, &adis16255_attr_group);
+	if (status != 0)
+		goto irq_err;

-	/* timebase = 1.953 ms, Ns = 0 -> 512 Hz sample rate */
-	value =  0x0001;
-	AD_CHK(spi_adis16255_write_data(spiadis,
-				ADIS_SMPL_PRD_MSB, ADIS_SMPL_PRD_LSB,
-				(u8 *)&value));
-	value = 0x0000;
-	AD_CHK(spi_adis16255_read_data(spiadis, ADIS_SMPL_PRD_MSB,
-				(u8 *)&value));
-	dev_info(&spi->dev, "adis SMP_PRD is %.4x\n", value);
+	status = spi_adis16255_bringup(spiadis);
+	if (status != 0)
+		goto irq_err;

-	/* set interrupt on new data... */
-	value = 0x0006;
-	AD_CHK(spi_adis16255_write_data(spiadis,
-				ADIS_MSC_CTRL_MSB, ADIS_MSC_CTRL_LSB,
-				(u8 *)&value));
-	value = 0x0000;
-	AD_CHK(spi_adis16255_read_data(spiadis, ADIS_MSC_CTRL_MSB,
-				(u8 *)&value));
-	dev_info(&spi->dev, "adis MSC_CONTROL is %.4x\n", value);
+	dev_info(&spi->dev, "spi_adis16255 driver added!\n");

 	return status;

 irq_err:
 	free_irq(spiadis->irq, spiadis);
 gpio_err:
-	gpio_free(spiadis->irq_adis);
+	gpio_free(init_data->irq);
 err:
 	kfree(spiadis);
 	return status;
@@ -362,11 +427,8 @@ static int spi_adis16255_remove(struct spi_device *spi)

 	spi_adis16255_shutdown(spiadis);

-	dev_info(&spi->dev, "unregister: GPIO %d IRQ %d\n",
-		spiadis->irq_adis, spiadis->irq);
-
 	free_irq(spiadis->irq, spiadis);
-	gpio_free(spiadis->irq_adis);
+	gpio_free(irq_to_gpio(spiadis->irq));

 	sysfs_remove_group(&spiadis->spi->dev.kobj, &adis16255_attr_group);


-- 
motzblog.wordpress.com
_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel


[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux