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 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 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 649dbf091dSManuel Stahl iio_trigger_notify_done(indio_dev->trig); 659dbf091dSManuel Stahl 669dbf091dSManuel Stahl error_ret: 679dbf091dSManuel Stahl return IRQ_HANDLED; 689dbf091dSManuel Stahl } 699dbf091dSManuel Stahl 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 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 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 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, 117*15ea2878SJonathan 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 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