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