1c78b9171SVlad Dogaru /* 2c78b9171SVlad Dogaru * Freescale MMA9551L Intelligent Motion-Sensing Platform driver 3c78b9171SVlad Dogaru * Copyright (c) 2014, Intel Corporation. 4c78b9171SVlad Dogaru * 5c78b9171SVlad Dogaru * This program is free software; you can redistribute it and/or modify it 6c78b9171SVlad Dogaru * under the terms and conditions of the GNU General Public License, 7c78b9171SVlad Dogaru * version 2, as published by the Free Software Foundation. 8c78b9171SVlad Dogaru * 9c78b9171SVlad Dogaru * This program is distributed in the hope it will be useful, but WITHOUT 10c78b9171SVlad Dogaru * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11c78b9171SVlad Dogaru * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12c78b9171SVlad Dogaru * more details. 13c78b9171SVlad Dogaru */ 14c78b9171SVlad Dogaru 15c78b9171SVlad Dogaru #include <linux/module.h> 16c78b9171SVlad Dogaru #include <linux/i2c.h> 17c78b9171SVlad Dogaru #include <linux/interrupt.h> 18c78b9171SVlad Dogaru #include <linux/slab.h> 19c78b9171SVlad Dogaru #include <linux/acpi.h> 20c78b9171SVlad Dogaru #include <linux/delay.h> 21c78b9171SVlad Dogaru #include <linux/gpio/consumer.h> 22c78b9171SVlad Dogaru #include <linux/iio/iio.h> 23c78b9171SVlad Dogaru #include <linux/iio/sysfs.h> 24c78b9171SVlad Dogaru #include <linux/iio/events.h> 256da93a67SIrina Tirdea #include <linux/pm_runtime.h> 26d5b97f5cSIrina Tirdea #include "mma9551_core.h" 27c78b9171SVlad Dogaru 28c78b9171SVlad Dogaru #define MMA9551_DRV_NAME "mma9551" 29c78b9171SVlad Dogaru #define MMA9551_IRQ_NAME "mma9551_event" 30c78b9171SVlad Dogaru #define MMA9551_GPIO_NAME "mma9551_int" 31c78b9171SVlad Dogaru #define MMA9551_GPIO_COUNT 4 32c78b9171SVlad Dogaru 33c78b9171SVlad Dogaru /* Tilt application (inclination in IIO terms). */ 34c78b9171SVlad Dogaru #define MMA9551_TILT_XZ_ANG_REG 0x00 35c78b9171SVlad Dogaru #define MMA9551_TILT_YZ_ANG_REG 0x01 36c78b9171SVlad Dogaru #define MMA9551_TILT_XY_ANG_REG 0x02 37c78b9171SVlad Dogaru #define MMA9551_TILT_ANGFLG BIT(7) 38c78b9171SVlad Dogaru #define MMA9551_TILT_QUAD_REG 0x03 39c78b9171SVlad Dogaru #define MMA9551_TILT_XY_QUAD_SHIFT 0 40c78b9171SVlad Dogaru #define MMA9551_TILT_YZ_QUAD_SHIFT 2 41c78b9171SVlad Dogaru #define MMA9551_TILT_XZ_QUAD_SHIFT 4 42c78b9171SVlad Dogaru #define MMA9551_TILT_CFG_REG 0x01 43c78b9171SVlad Dogaru #define MMA9551_TILT_ANG_THRESH_MASK GENMASK(3, 0) 44c78b9171SVlad Dogaru 45d5b97f5cSIrina Tirdea #define MMA9551_DEFAULT_SAMPLE_RATE 122 /* Hz */ 46d5b97f5cSIrina Tirdea 47c78b9171SVlad Dogaru /* Tilt events are mapped to the first three GPIO pins. */ 48c78b9171SVlad Dogaru enum mma9551_tilt_axis { 49c78b9171SVlad Dogaru mma9551_x = 0, 50c78b9171SVlad Dogaru mma9551_y, 51c78b9171SVlad Dogaru mma9551_z, 52c78b9171SVlad Dogaru }; 53c78b9171SVlad Dogaru 54c78b9171SVlad Dogaru struct mma9551_data { 55c78b9171SVlad Dogaru struct i2c_client *client; 56c78b9171SVlad Dogaru struct mutex mutex; 57c78b9171SVlad Dogaru int event_enabled[3]; 58c78b9171SVlad Dogaru int irqs[MMA9551_GPIO_COUNT]; 59c78b9171SVlad Dogaru }; 60c78b9171SVlad Dogaru 61c78b9171SVlad Dogaru static int mma9551_read_incli_chan(struct i2c_client *client, 62c78b9171SVlad Dogaru const struct iio_chan_spec *chan, 63c78b9171SVlad Dogaru int *val) 64c78b9171SVlad Dogaru { 65c78b9171SVlad Dogaru u8 quad_shift, angle, quadrant; 66c78b9171SVlad Dogaru u16 reg_addr; 67c78b9171SVlad Dogaru int ret; 68c78b9171SVlad Dogaru 69c78b9171SVlad Dogaru switch (chan->channel2) { 70c78b9171SVlad Dogaru case IIO_MOD_X: 71c78b9171SVlad Dogaru reg_addr = MMA9551_TILT_YZ_ANG_REG; 72c78b9171SVlad Dogaru quad_shift = MMA9551_TILT_YZ_QUAD_SHIFT; 73c78b9171SVlad Dogaru break; 74c78b9171SVlad Dogaru case IIO_MOD_Y: 75c78b9171SVlad Dogaru reg_addr = MMA9551_TILT_XZ_ANG_REG; 76c78b9171SVlad Dogaru quad_shift = MMA9551_TILT_XZ_QUAD_SHIFT; 77c78b9171SVlad Dogaru break; 78c78b9171SVlad Dogaru case IIO_MOD_Z: 79c78b9171SVlad Dogaru reg_addr = MMA9551_TILT_XY_ANG_REG; 80c78b9171SVlad Dogaru quad_shift = MMA9551_TILT_XY_QUAD_SHIFT; 81c78b9171SVlad Dogaru break; 82c78b9171SVlad Dogaru default: 83c78b9171SVlad Dogaru return -EINVAL; 84c78b9171SVlad Dogaru } 85c78b9171SVlad Dogaru 866da93a67SIrina Tirdea ret = mma9551_set_power_state(client, true); 87c78b9171SVlad Dogaru if (ret < 0) 88c78b9171SVlad Dogaru return ret; 89c78b9171SVlad Dogaru 90c78b9171SVlad Dogaru ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT, 916da93a67SIrina Tirdea reg_addr, &angle); 926da93a67SIrina Tirdea if (ret < 0) 936da93a67SIrina Tirdea goto out_poweroff; 946da93a67SIrina Tirdea 956da93a67SIrina Tirdea ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT, 96c78b9171SVlad Dogaru MMA9551_TILT_QUAD_REG, &quadrant); 97c78b9171SVlad Dogaru if (ret < 0) 986da93a67SIrina Tirdea goto out_poweroff; 99c78b9171SVlad Dogaru 100c78b9171SVlad Dogaru angle &= ~MMA9551_TILT_ANGFLG; 101c78b9171SVlad Dogaru quadrant = (quadrant >> quad_shift) & 0x03; 102c78b9171SVlad Dogaru 103c78b9171SVlad Dogaru if (quadrant == 1 || quadrant == 3) 104c78b9171SVlad Dogaru *val = 90 * (quadrant + 1) - angle; 105c78b9171SVlad Dogaru else 106c78b9171SVlad Dogaru *val = angle + 90 * quadrant; 107c78b9171SVlad Dogaru 1086da93a67SIrina Tirdea ret = IIO_VAL_INT; 1096da93a67SIrina Tirdea 1106da93a67SIrina Tirdea out_poweroff: 1116da93a67SIrina Tirdea mma9551_set_power_state(client, false); 1126da93a67SIrina Tirdea return ret; 113c78b9171SVlad Dogaru } 114c78b9171SVlad Dogaru 115c78b9171SVlad Dogaru static int mma9551_read_raw(struct iio_dev *indio_dev, 116c78b9171SVlad Dogaru struct iio_chan_spec const *chan, 117c78b9171SVlad Dogaru int *val, int *val2, long mask) 118c78b9171SVlad Dogaru { 119c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 120c78b9171SVlad Dogaru int ret; 121c78b9171SVlad Dogaru 122c78b9171SVlad Dogaru switch (mask) { 123c78b9171SVlad Dogaru case IIO_CHAN_INFO_PROCESSED: 124c78b9171SVlad Dogaru switch (chan->type) { 125c78b9171SVlad Dogaru case IIO_INCLI: 126c78b9171SVlad Dogaru mutex_lock(&data->mutex); 127c78b9171SVlad Dogaru ret = mma9551_read_incli_chan(data->client, chan, val); 128c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 129c78b9171SVlad Dogaru return ret; 130c78b9171SVlad Dogaru default: 131c78b9171SVlad Dogaru return -EINVAL; 132c78b9171SVlad Dogaru } 133c78b9171SVlad Dogaru case IIO_CHAN_INFO_RAW: 134c78b9171SVlad Dogaru switch (chan->type) { 135c78b9171SVlad Dogaru case IIO_ACCEL: 136c78b9171SVlad Dogaru mutex_lock(&data->mutex); 137c78b9171SVlad Dogaru ret = mma9551_read_accel_chan(data->client, 138c78b9171SVlad Dogaru chan, val, val2); 139c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 140c78b9171SVlad Dogaru return ret; 141c78b9171SVlad Dogaru default: 142c78b9171SVlad Dogaru return -EINVAL; 143c78b9171SVlad Dogaru } 144c78b9171SVlad Dogaru case IIO_CHAN_INFO_SCALE: 145c78b9171SVlad Dogaru switch (chan->type) { 146c78b9171SVlad Dogaru case IIO_ACCEL: 147d5b97f5cSIrina Tirdea return mma9551_read_accel_scale(val, val2); 148c78b9171SVlad Dogaru default: 149c78b9171SVlad Dogaru return -EINVAL; 150c78b9171SVlad Dogaru } 151c78b9171SVlad Dogaru default: 152c78b9171SVlad Dogaru return -EINVAL; 153c78b9171SVlad Dogaru } 154c78b9171SVlad Dogaru } 155c78b9171SVlad Dogaru 156c78b9171SVlad Dogaru static int mma9551_read_event_config(struct iio_dev *indio_dev, 157c78b9171SVlad Dogaru const struct iio_chan_spec *chan, 158c78b9171SVlad Dogaru enum iio_event_type type, 159c78b9171SVlad Dogaru enum iio_event_direction dir) 160c78b9171SVlad Dogaru { 161c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 162c78b9171SVlad Dogaru 163c78b9171SVlad Dogaru switch (chan->type) { 164c78b9171SVlad Dogaru case IIO_INCLI: 165c78b9171SVlad Dogaru /* IIO counts axes from 1, because IIO_NO_MOD is 0. */ 166c78b9171SVlad Dogaru return data->event_enabled[chan->channel2 - 1]; 167c78b9171SVlad Dogaru default: 168c78b9171SVlad Dogaru return -EINVAL; 169c78b9171SVlad Dogaru } 170c78b9171SVlad Dogaru } 171c78b9171SVlad Dogaru 172c78b9171SVlad Dogaru static int mma9551_config_incli_event(struct iio_dev *indio_dev, 173c78b9171SVlad Dogaru enum iio_modifier axis, 174c78b9171SVlad Dogaru int state) 175c78b9171SVlad Dogaru { 176c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 177c78b9171SVlad Dogaru enum mma9551_tilt_axis mma_axis; 178c78b9171SVlad Dogaru int ret; 179c78b9171SVlad Dogaru 180c78b9171SVlad Dogaru /* IIO counts axes from 1, because IIO_NO_MOD is 0. */ 181c78b9171SVlad Dogaru mma_axis = axis - 1; 182c78b9171SVlad Dogaru 183c78b9171SVlad Dogaru if (data->event_enabled[mma_axis] == state) 184c78b9171SVlad Dogaru return 0; 185c78b9171SVlad Dogaru 186c78b9171SVlad Dogaru if (state == 0) { 18760347e71SVlad Dogaru ret = mma9551_gpio_config(data->client, 18860347e71SVlad Dogaru (enum mma9551_gpio_pin)mma_axis, 189c78b9171SVlad Dogaru MMA9551_APPID_NONE, 0, 0); 190c78b9171SVlad Dogaru if (ret < 0) 191c78b9171SVlad Dogaru return ret; 1926da93a67SIrina Tirdea 1936da93a67SIrina Tirdea ret = mma9551_set_power_state(data->client, false); 1946da93a67SIrina Tirdea if (ret < 0) 1956da93a67SIrina Tirdea return ret; 196c78b9171SVlad Dogaru } else { 197c78b9171SVlad Dogaru int bitnum; 198c78b9171SVlad Dogaru 199c78b9171SVlad Dogaru /* Bit 7 of each angle register holds the angle flag. */ 200c78b9171SVlad Dogaru switch (axis) { 201c78b9171SVlad Dogaru case IIO_MOD_X: 202c78b9171SVlad Dogaru bitnum = 7 + 8 * MMA9551_TILT_YZ_ANG_REG; 203c78b9171SVlad Dogaru break; 204c78b9171SVlad Dogaru case IIO_MOD_Y: 205c78b9171SVlad Dogaru bitnum = 7 + 8 * MMA9551_TILT_XZ_ANG_REG; 206c78b9171SVlad Dogaru break; 207c78b9171SVlad Dogaru case IIO_MOD_Z: 208c78b9171SVlad Dogaru bitnum = 7 + 8 * MMA9551_TILT_XY_ANG_REG; 209c78b9171SVlad Dogaru break; 210c78b9171SVlad Dogaru default: 211c78b9171SVlad Dogaru return -EINVAL; 212c78b9171SVlad Dogaru } 213c78b9171SVlad Dogaru 2146da93a67SIrina Tirdea 2156da93a67SIrina Tirdea ret = mma9551_set_power_state(data->client, true); 2166da93a67SIrina Tirdea if (ret < 0) 2176da93a67SIrina Tirdea return ret; 2186da93a67SIrina Tirdea 21960347e71SVlad Dogaru ret = mma9551_gpio_config(data->client, 22060347e71SVlad Dogaru (enum mma9551_gpio_pin)mma_axis, 221c78b9171SVlad Dogaru MMA9551_APPID_TILT, bitnum, 0); 2226da93a67SIrina Tirdea if (ret < 0) { 2236da93a67SIrina Tirdea mma9551_set_power_state(data->client, false); 224c78b9171SVlad Dogaru return ret; 225c78b9171SVlad Dogaru } 2266da93a67SIrina Tirdea } 227c78b9171SVlad Dogaru 228c78b9171SVlad Dogaru data->event_enabled[mma_axis] = state; 229c78b9171SVlad Dogaru 230c78b9171SVlad Dogaru return ret; 231c78b9171SVlad Dogaru } 232c78b9171SVlad Dogaru 233c78b9171SVlad Dogaru static int mma9551_write_event_config(struct iio_dev *indio_dev, 234c78b9171SVlad Dogaru const struct iio_chan_spec *chan, 235c78b9171SVlad Dogaru enum iio_event_type type, 236c78b9171SVlad Dogaru enum iio_event_direction dir, 237c78b9171SVlad Dogaru int state) 238c78b9171SVlad Dogaru { 239c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 240c78b9171SVlad Dogaru int ret; 241c78b9171SVlad Dogaru 242c78b9171SVlad Dogaru switch (chan->type) { 243c78b9171SVlad Dogaru case IIO_INCLI: 244c78b9171SVlad Dogaru mutex_lock(&data->mutex); 245c78b9171SVlad Dogaru ret = mma9551_config_incli_event(indio_dev, 246c78b9171SVlad Dogaru chan->channel2, state); 247c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 248c78b9171SVlad Dogaru return ret; 249c78b9171SVlad Dogaru default: 250c78b9171SVlad Dogaru return -EINVAL; 251c78b9171SVlad Dogaru } 252c78b9171SVlad Dogaru } 253c78b9171SVlad Dogaru 254c78b9171SVlad Dogaru static int mma9551_write_event_value(struct iio_dev *indio_dev, 255c78b9171SVlad Dogaru const struct iio_chan_spec *chan, 256c78b9171SVlad Dogaru enum iio_event_type type, 257c78b9171SVlad Dogaru enum iio_event_direction dir, 258c78b9171SVlad Dogaru enum iio_event_info info, 259c78b9171SVlad Dogaru int val, int val2) 260c78b9171SVlad Dogaru { 261c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 262c78b9171SVlad Dogaru int ret; 263c78b9171SVlad Dogaru 264c78b9171SVlad Dogaru switch (chan->type) { 265c78b9171SVlad Dogaru case IIO_INCLI: 266c78b9171SVlad Dogaru if (val2 != 0 || val < 1 || val > 10) 267c78b9171SVlad Dogaru return -EINVAL; 268c78b9171SVlad Dogaru mutex_lock(&data->mutex); 269c78b9171SVlad Dogaru ret = mma9551_update_config_bits(data->client, 270c78b9171SVlad Dogaru MMA9551_APPID_TILT, 271c78b9171SVlad Dogaru MMA9551_TILT_CFG_REG, 272c78b9171SVlad Dogaru MMA9551_TILT_ANG_THRESH_MASK, 273c78b9171SVlad Dogaru val); 274c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 275c78b9171SVlad Dogaru return ret; 276c78b9171SVlad Dogaru default: 277c78b9171SVlad Dogaru return -EINVAL; 278c78b9171SVlad Dogaru } 279c78b9171SVlad Dogaru } 280c78b9171SVlad Dogaru 281c78b9171SVlad Dogaru static int mma9551_read_event_value(struct iio_dev *indio_dev, 282c78b9171SVlad Dogaru const struct iio_chan_spec *chan, 283c78b9171SVlad Dogaru enum iio_event_type type, 284c78b9171SVlad Dogaru enum iio_event_direction dir, 285c78b9171SVlad Dogaru enum iio_event_info info, 286c78b9171SVlad Dogaru int *val, int *val2) 287c78b9171SVlad Dogaru { 288c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 289c78b9171SVlad Dogaru int ret; 290c78b9171SVlad Dogaru u8 tmp; 291c78b9171SVlad Dogaru 292c78b9171SVlad Dogaru switch (chan->type) { 293c78b9171SVlad Dogaru case IIO_INCLI: 294c78b9171SVlad Dogaru mutex_lock(&data->mutex); 295c78b9171SVlad Dogaru ret = mma9551_read_config_byte(data->client, 296c78b9171SVlad Dogaru MMA9551_APPID_TILT, 297c78b9171SVlad Dogaru MMA9551_TILT_CFG_REG, &tmp); 298c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 299c78b9171SVlad Dogaru if (ret < 0) 300c78b9171SVlad Dogaru return ret; 301c78b9171SVlad Dogaru *val = tmp & MMA9551_TILT_ANG_THRESH_MASK; 302c78b9171SVlad Dogaru *val2 = 0; 303c78b9171SVlad Dogaru return IIO_VAL_INT; 304c78b9171SVlad Dogaru default: 305c78b9171SVlad Dogaru return -EINVAL; 306c78b9171SVlad Dogaru } 307c78b9171SVlad Dogaru } 308c78b9171SVlad Dogaru 309c78b9171SVlad Dogaru static const struct iio_event_spec mma9551_incli_event = { 310c78b9171SVlad Dogaru .type = IIO_EV_TYPE_ROC, 311c78b9171SVlad Dogaru .dir = IIO_EV_DIR_RISING, 312c78b9171SVlad Dogaru .mask_separate = BIT(IIO_EV_INFO_ENABLE), 313c78b9171SVlad Dogaru .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), 314c78b9171SVlad Dogaru }; 315c78b9171SVlad Dogaru 316c78b9171SVlad Dogaru #define MMA9551_INCLI_CHANNEL(axis) { \ 317c78b9171SVlad Dogaru .type = IIO_INCLI, \ 318c78b9171SVlad Dogaru .modified = 1, \ 319c78b9171SVlad Dogaru .channel2 = axis, \ 320c78b9171SVlad Dogaru .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ 321c78b9171SVlad Dogaru .event_spec = &mma9551_incli_event, \ 322c78b9171SVlad Dogaru .num_event_specs = 1, \ 323c78b9171SVlad Dogaru } 324c78b9171SVlad Dogaru 325c78b9171SVlad Dogaru static const struct iio_chan_spec mma9551_channels[] = { 326c78b9171SVlad Dogaru MMA9551_ACCEL_CHANNEL(IIO_MOD_X), 327c78b9171SVlad Dogaru MMA9551_ACCEL_CHANNEL(IIO_MOD_Y), 328c78b9171SVlad Dogaru MMA9551_ACCEL_CHANNEL(IIO_MOD_Z), 329c78b9171SVlad Dogaru 330c78b9171SVlad Dogaru MMA9551_INCLI_CHANNEL(IIO_MOD_X), 331c78b9171SVlad Dogaru MMA9551_INCLI_CHANNEL(IIO_MOD_Y), 332c78b9171SVlad Dogaru MMA9551_INCLI_CHANNEL(IIO_MOD_Z), 333c78b9171SVlad Dogaru }; 334c78b9171SVlad Dogaru 335c78b9171SVlad Dogaru static const struct iio_info mma9551_info = { 336c78b9171SVlad Dogaru .driver_module = THIS_MODULE, 337c78b9171SVlad Dogaru .read_raw = mma9551_read_raw, 338c78b9171SVlad Dogaru .read_event_config = mma9551_read_event_config, 339c78b9171SVlad Dogaru .write_event_config = mma9551_write_event_config, 340c78b9171SVlad Dogaru .read_event_value = mma9551_read_event_value, 341c78b9171SVlad Dogaru .write_event_value = mma9551_write_event_value, 342c78b9171SVlad Dogaru }; 343c78b9171SVlad Dogaru 344c78b9171SVlad Dogaru static irqreturn_t mma9551_event_handler(int irq, void *private) 345c78b9171SVlad Dogaru { 346c78b9171SVlad Dogaru struct iio_dev *indio_dev = private; 347c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 348c78b9171SVlad Dogaru int i, ret, mma_axis = -1; 349c78b9171SVlad Dogaru u16 reg; 350c78b9171SVlad Dogaru u8 val; 351c78b9171SVlad Dogaru 352c78b9171SVlad Dogaru mutex_lock(&data->mutex); 353c78b9171SVlad Dogaru 354c78b9171SVlad Dogaru for (i = 0; i < 3; i++) 355c78b9171SVlad Dogaru if (irq == data->irqs[i]) { 356c78b9171SVlad Dogaru mma_axis = i; 357c78b9171SVlad Dogaru break; 358c78b9171SVlad Dogaru } 359c78b9171SVlad Dogaru 360c78b9171SVlad Dogaru if (mma_axis == -1) { 361c78b9171SVlad Dogaru /* IRQ was triggered on 4th line, which we don't use. */ 362c78b9171SVlad Dogaru dev_warn(&data->client->dev, 363c78b9171SVlad Dogaru "irq triggered on unused line %d\n", data->irqs[3]); 364c78b9171SVlad Dogaru goto out; 365c78b9171SVlad Dogaru } 366c78b9171SVlad Dogaru 367c78b9171SVlad Dogaru switch (mma_axis) { 368c78b9171SVlad Dogaru case mma9551_x: 369c78b9171SVlad Dogaru reg = MMA9551_TILT_YZ_ANG_REG; 370c78b9171SVlad Dogaru break; 371c78b9171SVlad Dogaru case mma9551_y: 372c78b9171SVlad Dogaru reg = MMA9551_TILT_XZ_ANG_REG; 373c78b9171SVlad Dogaru break; 374c78b9171SVlad Dogaru case mma9551_z: 375c78b9171SVlad Dogaru reg = MMA9551_TILT_XY_ANG_REG; 376c78b9171SVlad Dogaru break; 377c78b9171SVlad Dogaru } 378c78b9171SVlad Dogaru 379c78b9171SVlad Dogaru /* 380c78b9171SVlad Dogaru * Read the angle even though we don't use it, otherwise we 381c78b9171SVlad Dogaru * won't get any further interrupts. 382c78b9171SVlad Dogaru */ 383c78b9171SVlad Dogaru ret = mma9551_read_status_byte(data->client, MMA9551_APPID_TILT, 384c78b9171SVlad Dogaru reg, &val); 385c78b9171SVlad Dogaru if (ret < 0) { 386c78b9171SVlad Dogaru dev_err(&data->client->dev, 387c78b9171SVlad Dogaru "error %d reading tilt register in IRQ\n", ret); 388c78b9171SVlad Dogaru goto out; 389c78b9171SVlad Dogaru } 390c78b9171SVlad Dogaru 391c78b9171SVlad Dogaru iio_push_event(indio_dev, 392c78b9171SVlad Dogaru IIO_MOD_EVENT_CODE(IIO_INCLI, 0, (mma_axis + 1), 393c78b9171SVlad Dogaru IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING), 394c78b9171SVlad Dogaru iio_get_time_ns()); 395c78b9171SVlad Dogaru 396c78b9171SVlad Dogaru out: 397c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 398c78b9171SVlad Dogaru 399c78b9171SVlad Dogaru return IRQ_HANDLED; 400c78b9171SVlad Dogaru } 401c78b9171SVlad Dogaru 402c78b9171SVlad Dogaru static int mma9551_init(struct mma9551_data *data) 403c78b9171SVlad Dogaru { 404c78b9171SVlad Dogaru int ret; 405c78b9171SVlad Dogaru 406c78b9171SVlad Dogaru ret = mma9551_read_version(data->client); 407c78b9171SVlad Dogaru if (ret) 408c78b9171SVlad Dogaru return ret; 409c78b9171SVlad Dogaru 4106da93a67SIrina Tirdea return mma9551_set_device_state(data->client, true); 411c78b9171SVlad Dogaru } 412c78b9171SVlad Dogaru 413c78b9171SVlad Dogaru static int mma9551_gpio_probe(struct iio_dev *indio_dev) 414c78b9171SVlad Dogaru { 415c78b9171SVlad Dogaru struct gpio_desc *gpio; 416c78b9171SVlad Dogaru int i, ret; 417c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 418c78b9171SVlad Dogaru struct device *dev = &data->client->dev; 419c78b9171SVlad Dogaru 420c78b9171SVlad Dogaru for (i = 0; i < MMA9551_GPIO_COUNT; i++) { 421b457f53aSUwe Kleine-König gpio = devm_gpiod_get_index(dev, MMA9551_GPIO_NAME, i, 422b457f53aSUwe Kleine-König GPIOD_IN); 423c78b9171SVlad Dogaru if (IS_ERR(gpio)) { 424c78b9171SVlad Dogaru dev_err(dev, "acpi gpio get index failed\n"); 425c78b9171SVlad Dogaru return PTR_ERR(gpio); 426c78b9171SVlad Dogaru } 427c78b9171SVlad Dogaru 428debf6d84SRoberta Dobrescu ret = gpiod_to_irq(gpio); 429debf6d84SRoberta Dobrescu if (ret < 0) 430debf6d84SRoberta Dobrescu return ret; 431debf6d84SRoberta Dobrescu 432debf6d84SRoberta Dobrescu data->irqs[i] = ret; 433c78b9171SVlad Dogaru ret = devm_request_threaded_irq(dev, data->irqs[i], 434c78b9171SVlad Dogaru NULL, mma9551_event_handler, 435c78b9171SVlad Dogaru IRQF_TRIGGER_RISING | IRQF_ONESHOT, 436c78b9171SVlad Dogaru MMA9551_IRQ_NAME, indio_dev); 437c78b9171SVlad Dogaru if (ret < 0) { 438c78b9171SVlad Dogaru dev_err(dev, "request irq %d failed\n", data->irqs[i]); 439c78b9171SVlad Dogaru return ret; 440c78b9171SVlad Dogaru } 441c78b9171SVlad Dogaru 442c78b9171SVlad Dogaru dev_dbg(dev, "gpio resource, no:%d irq:%d\n", 443c78b9171SVlad Dogaru desc_to_gpio(gpio), data->irqs[i]); 444c78b9171SVlad Dogaru } 445c78b9171SVlad Dogaru 446c78b9171SVlad Dogaru return 0; 447c78b9171SVlad Dogaru } 448c78b9171SVlad Dogaru 449c78b9171SVlad Dogaru static const char *mma9551_match_acpi_device(struct device *dev) 450c78b9171SVlad Dogaru { 451c78b9171SVlad Dogaru const struct acpi_device_id *id; 452c78b9171SVlad Dogaru 453c78b9171SVlad Dogaru id = acpi_match_device(dev->driver->acpi_match_table, dev); 454c78b9171SVlad Dogaru if (!id) 455c78b9171SVlad Dogaru return NULL; 456c78b9171SVlad Dogaru 457c78b9171SVlad Dogaru return dev_name(dev); 458c78b9171SVlad Dogaru } 459c78b9171SVlad Dogaru 460c78b9171SVlad Dogaru static int mma9551_probe(struct i2c_client *client, 461c78b9171SVlad Dogaru const struct i2c_device_id *id) 462c78b9171SVlad Dogaru { 463c78b9171SVlad Dogaru struct mma9551_data *data; 464c78b9171SVlad Dogaru struct iio_dev *indio_dev; 465c78b9171SVlad Dogaru const char *name = NULL; 466c78b9171SVlad Dogaru int ret; 467c78b9171SVlad Dogaru 468c78b9171SVlad Dogaru indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 469c78b9171SVlad Dogaru if (!indio_dev) 470c78b9171SVlad Dogaru return -ENOMEM; 471c78b9171SVlad Dogaru 472c78b9171SVlad Dogaru data = iio_priv(indio_dev); 473c78b9171SVlad Dogaru i2c_set_clientdata(client, indio_dev); 474c78b9171SVlad Dogaru data->client = client; 475c78b9171SVlad Dogaru 476c78b9171SVlad Dogaru if (id) 477c78b9171SVlad Dogaru name = id->name; 478c78b9171SVlad Dogaru else if (ACPI_HANDLE(&client->dev)) 479c78b9171SVlad Dogaru name = mma9551_match_acpi_device(&client->dev); 480c78b9171SVlad Dogaru 481c78b9171SVlad Dogaru ret = mma9551_init(data); 482c78b9171SVlad Dogaru if (ret < 0) 483c78b9171SVlad Dogaru return ret; 484c78b9171SVlad Dogaru 485c78b9171SVlad Dogaru mutex_init(&data->mutex); 486c78b9171SVlad Dogaru 487c78b9171SVlad Dogaru indio_dev->dev.parent = &client->dev; 488c78b9171SVlad Dogaru indio_dev->channels = mma9551_channels; 489c78b9171SVlad Dogaru indio_dev->num_channels = ARRAY_SIZE(mma9551_channels); 490c78b9171SVlad Dogaru indio_dev->name = name; 491c78b9171SVlad Dogaru indio_dev->modes = INDIO_DIRECT_MODE; 492c78b9171SVlad Dogaru indio_dev->info = &mma9551_info; 493c78b9171SVlad Dogaru 494c78b9171SVlad Dogaru ret = mma9551_gpio_probe(indio_dev); 495c78b9171SVlad Dogaru if (ret < 0) 496c78b9171SVlad Dogaru goto out_poweroff; 497c78b9171SVlad Dogaru 498c78b9171SVlad Dogaru ret = iio_device_register(indio_dev); 499c78b9171SVlad Dogaru if (ret < 0) { 500c78b9171SVlad Dogaru dev_err(&client->dev, "unable to register iio device\n"); 501c78b9171SVlad Dogaru goto out_poweroff; 502c78b9171SVlad Dogaru } 503c78b9171SVlad Dogaru 5046da93a67SIrina Tirdea ret = pm_runtime_set_active(&client->dev); 5056da93a67SIrina Tirdea if (ret < 0) 5066da93a67SIrina Tirdea goto out_iio_unregister; 5076da93a67SIrina Tirdea 5086da93a67SIrina Tirdea pm_runtime_enable(&client->dev); 5096da93a67SIrina Tirdea pm_runtime_set_autosuspend_delay(&client->dev, 5106da93a67SIrina Tirdea MMA9551_AUTO_SUSPEND_DELAY_MS); 5116da93a67SIrina Tirdea pm_runtime_use_autosuspend(&client->dev); 5126da93a67SIrina Tirdea 513c78b9171SVlad Dogaru return 0; 514c78b9171SVlad Dogaru 5156da93a67SIrina Tirdea out_iio_unregister: 5166da93a67SIrina Tirdea iio_device_unregister(indio_dev); 517c78b9171SVlad Dogaru out_poweroff: 518c78b9171SVlad Dogaru mma9551_set_device_state(client, false); 519c78b9171SVlad Dogaru 520c78b9171SVlad Dogaru return ret; 521c78b9171SVlad Dogaru } 522c78b9171SVlad Dogaru 523c78b9171SVlad Dogaru static int mma9551_remove(struct i2c_client *client) 524c78b9171SVlad Dogaru { 525c78b9171SVlad Dogaru struct iio_dev *indio_dev = i2c_get_clientdata(client); 526c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 527c78b9171SVlad Dogaru 5286da93a67SIrina Tirdea pm_runtime_disable(&client->dev); 5296da93a67SIrina Tirdea pm_runtime_set_suspended(&client->dev); 5306da93a67SIrina Tirdea pm_runtime_put_noidle(&client->dev); 5316da93a67SIrina Tirdea 532c78b9171SVlad Dogaru iio_device_unregister(indio_dev); 533c78b9171SVlad Dogaru mutex_lock(&data->mutex); 534c78b9171SVlad Dogaru mma9551_set_device_state(data->client, false); 535c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 536c78b9171SVlad Dogaru 537c78b9171SVlad Dogaru return 0; 538c78b9171SVlad Dogaru } 539c78b9171SVlad Dogaru 5406da93a67SIrina Tirdea #ifdef CONFIG_PM 5416da93a67SIrina Tirdea static int mma9551_runtime_suspend(struct device *dev) 5426da93a67SIrina Tirdea { 5436da93a67SIrina Tirdea struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 5446da93a67SIrina Tirdea struct mma9551_data *data = iio_priv(indio_dev); 5456da93a67SIrina Tirdea int ret; 5466da93a67SIrina Tirdea 5476da93a67SIrina Tirdea mutex_lock(&data->mutex); 5486da93a67SIrina Tirdea ret = mma9551_set_device_state(data->client, false); 5496da93a67SIrina Tirdea mutex_unlock(&data->mutex); 5506da93a67SIrina Tirdea if (ret < 0) { 5516da93a67SIrina Tirdea dev_err(&data->client->dev, "powering off device failed\n"); 5526da93a67SIrina Tirdea return -EAGAIN; 5536da93a67SIrina Tirdea } 5546da93a67SIrina Tirdea 5556da93a67SIrina Tirdea return 0; 5566da93a67SIrina Tirdea } 5576da93a67SIrina Tirdea 5586da93a67SIrina Tirdea static int mma9551_runtime_resume(struct device *dev) 5596da93a67SIrina Tirdea { 5606da93a67SIrina Tirdea struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 5616da93a67SIrina Tirdea struct mma9551_data *data = iio_priv(indio_dev); 5626da93a67SIrina Tirdea int ret; 5636da93a67SIrina Tirdea 5646da93a67SIrina Tirdea ret = mma9551_set_device_state(data->client, true); 5656da93a67SIrina Tirdea if (ret < 0) 5666da93a67SIrina Tirdea return ret; 5676da93a67SIrina Tirdea 5686da93a67SIrina Tirdea mma9551_sleep(MMA9551_DEFAULT_SAMPLE_RATE); 5696da93a67SIrina Tirdea 5706da93a67SIrina Tirdea return 0; 5716da93a67SIrina Tirdea } 5726da93a67SIrina Tirdea #endif 5736da93a67SIrina Tirdea 574c78b9171SVlad Dogaru #ifdef CONFIG_PM_SLEEP 575c78b9171SVlad Dogaru static int mma9551_suspend(struct device *dev) 576c78b9171SVlad Dogaru { 577c78b9171SVlad Dogaru struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 578c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 5796da93a67SIrina Tirdea int ret; 580c78b9171SVlad Dogaru 581c78b9171SVlad Dogaru mutex_lock(&data->mutex); 5826da93a67SIrina Tirdea ret = mma9551_set_device_state(data->client, false); 583c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 584c78b9171SVlad Dogaru 5856da93a67SIrina Tirdea return ret; 586c78b9171SVlad Dogaru } 587c78b9171SVlad Dogaru 588c78b9171SVlad Dogaru static int mma9551_resume(struct device *dev) 589c78b9171SVlad Dogaru { 590c78b9171SVlad Dogaru struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 591c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 5926da93a67SIrina Tirdea int ret; 593c78b9171SVlad Dogaru 594c78b9171SVlad Dogaru mutex_lock(&data->mutex); 5956da93a67SIrina Tirdea ret = mma9551_set_device_state(data->client, true); 596c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 597c78b9171SVlad Dogaru 5986da93a67SIrina Tirdea return ret; 599c78b9171SVlad Dogaru } 600c78b9171SVlad Dogaru #endif 601c78b9171SVlad Dogaru 602c78b9171SVlad Dogaru static const struct dev_pm_ops mma9551_pm_ops = { 603c78b9171SVlad Dogaru SET_SYSTEM_SLEEP_PM_OPS(mma9551_suspend, mma9551_resume) 6046da93a67SIrina Tirdea SET_RUNTIME_PM_OPS(mma9551_runtime_suspend, 6056da93a67SIrina Tirdea mma9551_runtime_resume, NULL) 606c78b9171SVlad Dogaru }; 607c78b9171SVlad Dogaru 608c78b9171SVlad Dogaru static const struct acpi_device_id mma9551_acpi_match[] = { 609c78b9171SVlad Dogaru {"MMA9551", 0}, 610c78b9171SVlad Dogaru {}, 611c78b9171SVlad Dogaru }; 612c78b9171SVlad Dogaru 613c78b9171SVlad Dogaru MODULE_DEVICE_TABLE(acpi, mma9551_acpi_match); 614c78b9171SVlad Dogaru 615c78b9171SVlad Dogaru static const struct i2c_device_id mma9551_id[] = { 616c78b9171SVlad Dogaru {"mma9551", 0}, 617c78b9171SVlad Dogaru {} 618c78b9171SVlad Dogaru }; 619c78b9171SVlad Dogaru 620c78b9171SVlad Dogaru MODULE_DEVICE_TABLE(i2c, mma9551_id); 621c78b9171SVlad Dogaru 622c78b9171SVlad Dogaru static struct i2c_driver mma9551_driver = { 623c78b9171SVlad Dogaru .driver = { 624c78b9171SVlad Dogaru .name = MMA9551_DRV_NAME, 625c78b9171SVlad Dogaru .acpi_match_table = ACPI_PTR(mma9551_acpi_match), 626c78b9171SVlad Dogaru .pm = &mma9551_pm_ops, 627c78b9171SVlad Dogaru }, 628c78b9171SVlad Dogaru .probe = mma9551_probe, 629c78b9171SVlad Dogaru .remove = mma9551_remove, 630c78b9171SVlad Dogaru .id_table = mma9551_id, 631c78b9171SVlad Dogaru }; 632c78b9171SVlad Dogaru 633c78b9171SVlad Dogaru module_i2c_driver(mma9551_driver); 634c78b9171SVlad Dogaru 635c78b9171SVlad Dogaru MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>"); 636c78b9171SVlad Dogaru MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>"); 637c78b9171SVlad Dogaru MODULE_LICENSE("GPL v2"); 638c78b9171SVlad Dogaru MODULE_DESCRIPTION("MMA9551L motion-sensing platform driver"); 639