1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
29dbf091dSManuel Stahl /*
39dbf091dSManuel Stahl  * itg3200_buffer.c -- support InvenSense ITG3200
49dbf091dSManuel Stahl  *                     Digital 3-Axis Gyroscope driver
59dbf091dSManuel Stahl  *
69dbf091dSManuel Stahl  * Copyright (c) 2011 Christian Strobel <christian.strobel@iis.fraunhofer.de>
79dbf091dSManuel Stahl  * Copyright (c) 2011 Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
89dbf091dSManuel Stahl  * Copyright (c) 2012 Thorsten Nowak <thorsten.nowak@iis.fraunhofer.de>
99dbf091dSManuel Stahl  */
109dbf091dSManuel Stahl 
119dbf091dSManuel Stahl #include <linux/slab.h>
129dbf091dSManuel Stahl #include <linux/i2c.h>
139dbf091dSManuel Stahl #include <linux/interrupt.h>
149dbf091dSManuel Stahl 
159dbf091dSManuel Stahl #include <linux/iio/iio.h>
169dbf091dSManuel Stahl #include <linux/iio/buffer.h>
179dbf091dSManuel Stahl #include <linux/iio/trigger.h>
189dbf091dSManuel Stahl #include <linux/iio/trigger_consumer.h>
199dbf091dSManuel Stahl #include <linux/iio/triggered_buffer.h>
209dbf091dSManuel Stahl #include <linux/iio/gyro/itg3200.h>
219dbf091dSManuel Stahl 
229dbf091dSManuel Stahl 
itg3200_read_all_channels(struct i2c_client * i2c,__be16 * buf)239dbf091dSManuel Stahl static int itg3200_read_all_channels(struct i2c_client *i2c, __be16 *buf)
249dbf091dSManuel Stahl {
259dbf091dSManuel Stahl 	u8 tx = 0x80 | ITG3200_REG_TEMP_OUT_H;
269dbf091dSManuel Stahl 	struct i2c_msg msg[2] = {
279dbf091dSManuel Stahl 		{
289dbf091dSManuel Stahl 			.addr = i2c->addr,
299dbf091dSManuel Stahl 			.flags = i2c->flags,
309dbf091dSManuel Stahl 			.len = 1,
319dbf091dSManuel Stahl 			.buf = &tx,
329dbf091dSManuel Stahl 		},
339dbf091dSManuel Stahl 		{
349dbf091dSManuel Stahl 			.addr = i2c->addr,
359dbf091dSManuel Stahl 			.flags = i2c->flags | I2C_M_RD,
369dbf091dSManuel Stahl 			.len = ITG3200_SCAN_ELEMENTS * sizeof(s16),
379dbf091dSManuel Stahl 			.buf = (char *)&buf,
389dbf091dSManuel Stahl 		},
399dbf091dSManuel Stahl 	};
409dbf091dSManuel Stahl 
419dbf091dSManuel Stahl 	return i2c_transfer(i2c->adapter, msg, 2);
429dbf091dSManuel Stahl }
439dbf091dSManuel Stahl 
itg3200_trigger_handler(int irq,void * p)449dbf091dSManuel Stahl static irqreturn_t itg3200_trigger_handler(int irq, void *p)
459dbf091dSManuel Stahl {
469dbf091dSManuel Stahl 	struct iio_poll_func *pf = p;
479dbf091dSManuel Stahl 	struct iio_dev *indio_dev = pf->indio_dev;
489dbf091dSManuel Stahl 	struct itg3200 *st = iio_priv(indio_dev);
4910ab7cfdSJonathan Cameron 	/*
5010ab7cfdSJonathan Cameron 	 * Ensure correct alignment and padding including for the
5110ab7cfdSJonathan Cameron 	 * timestamp that may be inserted.
5210ab7cfdSJonathan Cameron 	 */
5310ab7cfdSJonathan Cameron 	struct {
5410ab7cfdSJonathan Cameron 		__be16 buf[ITG3200_SCAN_ELEMENTS];
5510ab7cfdSJonathan Cameron 		s64 ts __aligned(8);
5610ab7cfdSJonathan Cameron 	} scan;
579dbf091dSManuel Stahl 
5810ab7cfdSJonathan Cameron 	int ret = itg3200_read_all_channels(st->i2c, scan.buf);
599dbf091dSManuel Stahl 	if (ret < 0)
609dbf091dSManuel Stahl 		goto error_ret;
619dbf091dSManuel Stahl 
6210ab7cfdSJonathan Cameron 	iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp);
639dbf091dSManuel Stahl 
64*363e1286SLars-Peter Clausen error_ret:
659dbf091dSManuel Stahl 	iio_trigger_notify_done(indio_dev->trig);
669dbf091dSManuel Stahl 
679dbf091dSManuel Stahl 	return IRQ_HANDLED;
689dbf091dSManuel Stahl }
699dbf091dSManuel Stahl 
itg3200_buffer_configure(struct iio_dev * indio_dev)709dbf091dSManuel Stahl int itg3200_buffer_configure(struct iio_dev *indio_dev)
719dbf091dSManuel Stahl {
729dbf091dSManuel Stahl 	return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
739dbf091dSManuel Stahl 		itg3200_trigger_handler, NULL);
749dbf091dSManuel Stahl }
759dbf091dSManuel Stahl 
itg3200_buffer_unconfigure(struct iio_dev * indio_dev)769dbf091dSManuel Stahl void itg3200_buffer_unconfigure(struct iio_dev *indio_dev)
779dbf091dSManuel Stahl {
789dbf091dSManuel Stahl 	iio_triggered_buffer_cleanup(indio_dev);
799dbf091dSManuel Stahl }
809dbf091dSManuel Stahl 
819dbf091dSManuel Stahl 
itg3200_data_rdy_trigger_set_state(struct iio_trigger * trig,bool state)829dbf091dSManuel Stahl static int itg3200_data_rdy_trigger_set_state(struct iio_trigger *trig,
839dbf091dSManuel Stahl 		bool state)
849dbf091dSManuel Stahl {
851e9663c6SLars-Peter Clausen 	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
869dbf091dSManuel Stahl 	int ret;
879dbf091dSManuel Stahl 	u8 msc;
889dbf091dSManuel Stahl 
899dbf091dSManuel Stahl 	ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_IRQ_CONFIG, &msc);
909dbf091dSManuel Stahl 	if (ret)
919dbf091dSManuel Stahl 		goto error_ret;
929dbf091dSManuel Stahl 
939dbf091dSManuel Stahl 	if (state)
949dbf091dSManuel Stahl 		msc |= ITG3200_IRQ_DATA_RDY_ENABLE;
959dbf091dSManuel Stahl 	else
969dbf091dSManuel Stahl 		msc &= ~ITG3200_IRQ_DATA_RDY_ENABLE;
979dbf091dSManuel Stahl 
989dbf091dSManuel Stahl 	ret = itg3200_write_reg_8(indio_dev, ITG3200_REG_IRQ_CONFIG, msc);
999dbf091dSManuel Stahl 	if (ret)
1009dbf091dSManuel Stahl 		goto error_ret;
1019dbf091dSManuel Stahl 
1029dbf091dSManuel Stahl error_ret:
1039dbf091dSManuel Stahl 	return ret;
1049dbf091dSManuel Stahl 
1059dbf091dSManuel Stahl }
1069dbf091dSManuel Stahl 
1079dbf091dSManuel Stahl static const struct iio_trigger_ops itg3200_trigger_ops = {
1089dbf091dSManuel Stahl 	.set_trigger_state = &itg3200_data_rdy_trigger_set_state,
1099dbf091dSManuel Stahl };
1109dbf091dSManuel Stahl 
itg3200_probe_trigger(struct iio_dev * indio_dev)1119dbf091dSManuel Stahl int itg3200_probe_trigger(struct iio_dev *indio_dev)
1129dbf091dSManuel Stahl {
1139dbf091dSManuel Stahl 	int ret;
1149dbf091dSManuel Stahl 	struct itg3200 *st = iio_priv(indio_dev);
1159dbf091dSManuel Stahl 
116995071d3SGwendal Grignou 	st->trig = iio_trigger_alloc(&st->i2c->dev, "%s-dev%d", indio_dev->name,
11715ea2878SJonathan Cameron 				     iio_device_id(indio_dev));
1189dbf091dSManuel Stahl 	if (!st->trig)
1199dbf091dSManuel Stahl 		return -ENOMEM;
1209dbf091dSManuel Stahl 
1219dbf091dSManuel Stahl 	ret = request_irq(st->i2c->irq,
1229dbf091dSManuel Stahl 			  &iio_trigger_generic_data_rdy_poll,
1239dbf091dSManuel Stahl 			  IRQF_TRIGGER_RISING,
1249dbf091dSManuel Stahl 			  "itg3200_data_rdy",
1259dbf091dSManuel Stahl 			  st->trig);
1269dbf091dSManuel Stahl 	if (ret)
1279dbf091dSManuel Stahl 		goto error_free_trig;
1289dbf091dSManuel Stahl 
1299dbf091dSManuel Stahl 
1309dbf091dSManuel Stahl 	st->trig->ops = &itg3200_trigger_ops;
1311e9663c6SLars-Peter Clausen 	iio_trigger_set_drvdata(st->trig, indio_dev);
1329dbf091dSManuel Stahl 	ret = iio_trigger_register(st->trig);
1339dbf091dSManuel Stahl 	if (ret)
1349dbf091dSManuel Stahl 		goto error_free_irq;
1359dbf091dSManuel Stahl 
1369dbf091dSManuel Stahl 	/* select default trigger */
1370b4dce2eSSrinivas Pandruvada 	indio_dev->trig = iio_trigger_get(st->trig);
1389dbf091dSManuel Stahl 
1399dbf091dSManuel Stahl 	return 0;
1409dbf091dSManuel Stahl 
1419dbf091dSManuel Stahl error_free_irq:
1429dbf091dSManuel Stahl 	free_irq(st->i2c->irq, st->trig);
1439dbf091dSManuel Stahl error_free_trig:
1449dbf091dSManuel Stahl 	iio_trigger_free(st->trig);
1459dbf091dSManuel Stahl 	return ret;
1469dbf091dSManuel Stahl }
1479dbf091dSManuel Stahl 
itg3200_remove_trigger(struct iio_dev * indio_dev)1489dbf091dSManuel Stahl void itg3200_remove_trigger(struct iio_dev *indio_dev)
1499dbf091dSManuel Stahl {
1509dbf091dSManuel Stahl 	struct itg3200 *st = iio_priv(indio_dev);
1519dbf091dSManuel Stahl 
1529dbf091dSManuel Stahl 	iio_trigger_unregister(st->trig);
1539dbf091dSManuel Stahl 	free_irq(st->i2c->irq, st->trig);
1549dbf091dSManuel Stahl 	iio_trigger_free(st->trig);
1559dbf091dSManuel Stahl }
156