12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2c78b9171SVlad Dogaru /* 3c78b9171SVlad Dogaru * Freescale MMA9551L Intelligent Motion-Sensing Platform driver 4c78b9171SVlad Dogaru * Copyright (c) 2014, Intel Corporation. 5c78b9171SVlad Dogaru */ 6c78b9171SVlad Dogaru 7c78b9171SVlad Dogaru #include <linux/module.h> 8c78b9171SVlad Dogaru #include <linux/i2c.h> 9c78b9171SVlad Dogaru #include <linux/interrupt.h> 10c78b9171SVlad Dogaru #include <linux/slab.h> 11c78b9171SVlad Dogaru #include <linux/acpi.h> 12c78b9171SVlad Dogaru #include <linux/delay.h> 13c78b9171SVlad Dogaru #include <linux/gpio/consumer.h> 14c78b9171SVlad Dogaru #include <linux/iio/iio.h> 15c78b9171SVlad Dogaru #include <linux/iio/sysfs.h> 16c78b9171SVlad Dogaru #include <linux/iio/events.h> 176da93a67SIrina Tirdea #include <linux/pm_runtime.h> 18d5b97f5cSIrina Tirdea #include "mma9551_core.h" 19c78b9171SVlad Dogaru 20c78b9171SVlad Dogaru #define MMA9551_DRV_NAME "mma9551" 21c78b9171SVlad Dogaru #define MMA9551_IRQ_NAME "mma9551_event" 22c78b9171SVlad Dogaru #define MMA9551_GPIO_COUNT 4 23c78b9171SVlad Dogaru 24c78b9171SVlad Dogaru /* Tilt application (inclination in IIO terms). */ 25c78b9171SVlad Dogaru #define MMA9551_TILT_XZ_ANG_REG 0x00 26c78b9171SVlad Dogaru #define MMA9551_TILT_YZ_ANG_REG 0x01 27c78b9171SVlad Dogaru #define MMA9551_TILT_XY_ANG_REG 0x02 28c78b9171SVlad Dogaru #define MMA9551_TILT_ANGFLG BIT(7) 29c78b9171SVlad Dogaru #define MMA9551_TILT_QUAD_REG 0x03 30c78b9171SVlad Dogaru #define MMA9551_TILT_XY_QUAD_SHIFT 0 31c78b9171SVlad Dogaru #define MMA9551_TILT_YZ_QUAD_SHIFT 2 32c78b9171SVlad Dogaru #define MMA9551_TILT_XZ_QUAD_SHIFT 4 33c78b9171SVlad Dogaru #define MMA9551_TILT_CFG_REG 0x01 34c78b9171SVlad Dogaru #define MMA9551_TILT_ANG_THRESH_MASK GENMASK(3, 0) 35c78b9171SVlad Dogaru 36d5b97f5cSIrina Tirdea #define MMA9551_DEFAULT_SAMPLE_RATE 122 /* Hz */ 37d5b97f5cSIrina Tirdea 38c78b9171SVlad Dogaru /* Tilt events are mapped to the first three GPIO pins. */ 39c78b9171SVlad Dogaru enum mma9551_tilt_axis { 40c78b9171SVlad Dogaru mma9551_x = 0, 41c78b9171SVlad Dogaru mma9551_y, 42c78b9171SVlad Dogaru mma9551_z, 43c78b9171SVlad Dogaru }; 44c78b9171SVlad Dogaru 45c78b9171SVlad Dogaru struct mma9551_data { 46c78b9171SVlad Dogaru struct i2c_client *client; 47c78b9171SVlad Dogaru struct mutex mutex; 48c78b9171SVlad Dogaru int event_enabled[3]; 49c78b9171SVlad Dogaru int irqs[MMA9551_GPIO_COUNT]; 50c78b9171SVlad Dogaru }; 51c78b9171SVlad Dogaru 52c78b9171SVlad Dogaru static int mma9551_read_incli_chan(struct i2c_client *client, 53c78b9171SVlad Dogaru const struct iio_chan_spec *chan, 54c78b9171SVlad Dogaru int *val) 55c78b9171SVlad Dogaru { 56c78b9171SVlad Dogaru u8 quad_shift, angle, quadrant; 57c78b9171SVlad Dogaru u16 reg_addr; 58c78b9171SVlad Dogaru int ret; 59c78b9171SVlad Dogaru 60c78b9171SVlad Dogaru switch (chan->channel2) { 61c78b9171SVlad Dogaru case IIO_MOD_X: 62c78b9171SVlad Dogaru reg_addr = MMA9551_TILT_YZ_ANG_REG; 63c78b9171SVlad Dogaru quad_shift = MMA9551_TILT_YZ_QUAD_SHIFT; 64c78b9171SVlad Dogaru break; 65c78b9171SVlad Dogaru case IIO_MOD_Y: 66c78b9171SVlad Dogaru reg_addr = MMA9551_TILT_XZ_ANG_REG; 67c78b9171SVlad Dogaru quad_shift = MMA9551_TILT_XZ_QUAD_SHIFT; 68c78b9171SVlad Dogaru break; 69c78b9171SVlad Dogaru case IIO_MOD_Z: 70c78b9171SVlad Dogaru reg_addr = MMA9551_TILT_XY_ANG_REG; 71c78b9171SVlad Dogaru quad_shift = MMA9551_TILT_XY_QUAD_SHIFT; 72c78b9171SVlad Dogaru break; 73c78b9171SVlad Dogaru default: 74c78b9171SVlad Dogaru return -EINVAL; 75c78b9171SVlad Dogaru } 76c78b9171SVlad Dogaru 776da93a67SIrina Tirdea ret = mma9551_set_power_state(client, true); 78c78b9171SVlad Dogaru if (ret < 0) 79c78b9171SVlad Dogaru return ret; 80c78b9171SVlad Dogaru 81c78b9171SVlad Dogaru ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT, 826da93a67SIrina Tirdea reg_addr, &angle); 836da93a67SIrina Tirdea if (ret < 0) 846da93a67SIrina Tirdea goto out_poweroff; 856da93a67SIrina Tirdea 866da93a67SIrina Tirdea ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT, 87c78b9171SVlad Dogaru MMA9551_TILT_QUAD_REG, &quadrant); 88c78b9171SVlad Dogaru if (ret < 0) 896da93a67SIrina Tirdea goto out_poweroff; 90c78b9171SVlad Dogaru 91c78b9171SVlad Dogaru angle &= ~MMA9551_TILT_ANGFLG; 92c78b9171SVlad Dogaru quadrant = (quadrant >> quad_shift) & 0x03; 93c78b9171SVlad Dogaru 94c78b9171SVlad Dogaru if (quadrant == 1 || quadrant == 3) 95c78b9171SVlad Dogaru *val = 90 * (quadrant + 1) - angle; 96c78b9171SVlad Dogaru else 97c78b9171SVlad Dogaru *val = angle + 90 * quadrant; 98c78b9171SVlad Dogaru 996da93a67SIrina Tirdea ret = IIO_VAL_INT; 1006da93a67SIrina Tirdea 1016da93a67SIrina Tirdea out_poweroff: 1026da93a67SIrina Tirdea mma9551_set_power_state(client, false); 1036da93a67SIrina Tirdea return ret; 104c78b9171SVlad Dogaru } 105c78b9171SVlad Dogaru 106c78b9171SVlad Dogaru static int mma9551_read_raw(struct iio_dev *indio_dev, 107c78b9171SVlad Dogaru struct iio_chan_spec const *chan, 108c78b9171SVlad Dogaru int *val, int *val2, long mask) 109c78b9171SVlad Dogaru { 110c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 111c78b9171SVlad Dogaru int ret; 112c78b9171SVlad Dogaru 113c78b9171SVlad Dogaru switch (mask) { 114c78b9171SVlad Dogaru case IIO_CHAN_INFO_PROCESSED: 115c78b9171SVlad Dogaru switch (chan->type) { 116c78b9171SVlad Dogaru case IIO_INCLI: 117c78b9171SVlad Dogaru mutex_lock(&data->mutex); 118c78b9171SVlad Dogaru ret = mma9551_read_incli_chan(data->client, chan, val); 119c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 120c78b9171SVlad Dogaru return ret; 121c78b9171SVlad Dogaru default: 122c78b9171SVlad Dogaru return -EINVAL; 123c78b9171SVlad Dogaru } 124c78b9171SVlad Dogaru case IIO_CHAN_INFO_RAW: 125c78b9171SVlad Dogaru switch (chan->type) { 126c78b9171SVlad Dogaru case IIO_ACCEL: 127c78b9171SVlad Dogaru mutex_lock(&data->mutex); 128c78b9171SVlad Dogaru ret = mma9551_read_accel_chan(data->client, 129c78b9171SVlad Dogaru chan, val, val2); 130c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 131c78b9171SVlad Dogaru return ret; 132c78b9171SVlad Dogaru default: 133c78b9171SVlad Dogaru return -EINVAL; 134c78b9171SVlad Dogaru } 135c78b9171SVlad Dogaru case IIO_CHAN_INFO_SCALE: 136c78b9171SVlad Dogaru switch (chan->type) { 137c78b9171SVlad Dogaru case IIO_ACCEL: 138d5b97f5cSIrina Tirdea return mma9551_read_accel_scale(val, val2); 139c78b9171SVlad Dogaru default: 140c78b9171SVlad Dogaru return -EINVAL; 141c78b9171SVlad Dogaru } 142c78b9171SVlad Dogaru default: 143c78b9171SVlad Dogaru return -EINVAL; 144c78b9171SVlad Dogaru } 145c78b9171SVlad Dogaru } 146c78b9171SVlad Dogaru 147c78b9171SVlad Dogaru static int mma9551_read_event_config(struct iio_dev *indio_dev, 148c78b9171SVlad Dogaru const struct iio_chan_spec *chan, 149c78b9171SVlad Dogaru enum iio_event_type type, 150c78b9171SVlad Dogaru enum iio_event_direction dir) 151c78b9171SVlad Dogaru { 152c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 153c78b9171SVlad Dogaru 154c78b9171SVlad Dogaru switch (chan->type) { 155c78b9171SVlad Dogaru case IIO_INCLI: 156c78b9171SVlad Dogaru /* IIO counts axes from 1, because IIO_NO_MOD is 0. */ 157c78b9171SVlad Dogaru return data->event_enabled[chan->channel2 - 1]; 158c78b9171SVlad Dogaru default: 159c78b9171SVlad Dogaru return -EINVAL; 160c78b9171SVlad Dogaru } 161c78b9171SVlad Dogaru } 162c78b9171SVlad Dogaru 163c78b9171SVlad Dogaru static int mma9551_config_incli_event(struct iio_dev *indio_dev, 164c78b9171SVlad Dogaru enum iio_modifier axis, 165c78b9171SVlad Dogaru int state) 166c78b9171SVlad Dogaru { 167c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 168c78b9171SVlad Dogaru enum mma9551_tilt_axis mma_axis; 169c78b9171SVlad Dogaru int ret; 170c78b9171SVlad Dogaru 171c78b9171SVlad Dogaru /* IIO counts axes from 1, because IIO_NO_MOD is 0. */ 172c78b9171SVlad Dogaru mma_axis = axis - 1; 173c78b9171SVlad Dogaru 174c78b9171SVlad Dogaru if (data->event_enabled[mma_axis] == state) 175c78b9171SVlad Dogaru return 0; 176c78b9171SVlad Dogaru 177c78b9171SVlad Dogaru if (state == 0) { 17860347e71SVlad Dogaru ret = mma9551_gpio_config(data->client, 17960347e71SVlad Dogaru (enum mma9551_gpio_pin)mma_axis, 180c78b9171SVlad Dogaru MMA9551_APPID_NONE, 0, 0); 181c78b9171SVlad Dogaru if (ret < 0) 182c78b9171SVlad Dogaru return ret; 1836da93a67SIrina Tirdea 1846da93a67SIrina Tirdea ret = mma9551_set_power_state(data->client, false); 1856da93a67SIrina Tirdea if (ret < 0) 1866da93a67SIrina Tirdea return ret; 187c78b9171SVlad Dogaru } else { 188c78b9171SVlad Dogaru int bitnum; 189c78b9171SVlad Dogaru 190c78b9171SVlad Dogaru /* Bit 7 of each angle register holds the angle flag. */ 191c78b9171SVlad Dogaru switch (axis) { 192c78b9171SVlad Dogaru case IIO_MOD_X: 193c78b9171SVlad Dogaru bitnum = 7 + 8 * MMA9551_TILT_YZ_ANG_REG; 194c78b9171SVlad Dogaru break; 195c78b9171SVlad Dogaru case IIO_MOD_Y: 196c78b9171SVlad Dogaru bitnum = 7 + 8 * MMA9551_TILT_XZ_ANG_REG; 197c78b9171SVlad Dogaru break; 198c78b9171SVlad Dogaru case IIO_MOD_Z: 199c78b9171SVlad Dogaru bitnum = 7 + 8 * MMA9551_TILT_XY_ANG_REG; 200c78b9171SVlad Dogaru break; 201c78b9171SVlad Dogaru default: 202c78b9171SVlad Dogaru return -EINVAL; 203c78b9171SVlad Dogaru } 204c78b9171SVlad Dogaru 2056da93a67SIrina Tirdea 2066da93a67SIrina Tirdea ret = mma9551_set_power_state(data->client, true); 2076da93a67SIrina Tirdea if (ret < 0) 2086da93a67SIrina Tirdea return ret; 2096da93a67SIrina Tirdea 21060347e71SVlad Dogaru ret = mma9551_gpio_config(data->client, 21160347e71SVlad Dogaru (enum mma9551_gpio_pin)mma_axis, 212c78b9171SVlad Dogaru MMA9551_APPID_TILT, bitnum, 0); 2136da93a67SIrina Tirdea if (ret < 0) { 2146da93a67SIrina Tirdea mma9551_set_power_state(data->client, false); 215c78b9171SVlad Dogaru return ret; 216c78b9171SVlad Dogaru } 2176da93a67SIrina Tirdea } 218c78b9171SVlad Dogaru 219c78b9171SVlad Dogaru data->event_enabled[mma_axis] = state; 220c78b9171SVlad Dogaru 221c78b9171SVlad Dogaru return ret; 222c78b9171SVlad Dogaru } 223c78b9171SVlad Dogaru 224c78b9171SVlad Dogaru static int mma9551_write_event_config(struct iio_dev *indio_dev, 225c78b9171SVlad Dogaru const struct iio_chan_spec *chan, 226c78b9171SVlad Dogaru enum iio_event_type type, 227c78b9171SVlad Dogaru enum iio_event_direction dir, 228c78b9171SVlad Dogaru int state) 229c78b9171SVlad Dogaru { 230c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 231c78b9171SVlad Dogaru int ret; 232c78b9171SVlad Dogaru 233c78b9171SVlad Dogaru switch (chan->type) { 234c78b9171SVlad Dogaru case IIO_INCLI: 235c78b9171SVlad Dogaru mutex_lock(&data->mutex); 236c78b9171SVlad Dogaru ret = mma9551_config_incli_event(indio_dev, 237c78b9171SVlad Dogaru chan->channel2, state); 238c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 239c78b9171SVlad Dogaru return ret; 240c78b9171SVlad Dogaru default: 241c78b9171SVlad Dogaru return -EINVAL; 242c78b9171SVlad Dogaru } 243c78b9171SVlad Dogaru } 244c78b9171SVlad Dogaru 245c78b9171SVlad Dogaru static int mma9551_write_event_value(struct iio_dev *indio_dev, 246c78b9171SVlad Dogaru const struct iio_chan_spec *chan, 247c78b9171SVlad Dogaru enum iio_event_type type, 248c78b9171SVlad Dogaru enum iio_event_direction dir, 249c78b9171SVlad Dogaru enum iio_event_info info, 250c78b9171SVlad Dogaru int val, int val2) 251c78b9171SVlad Dogaru { 252c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 253c78b9171SVlad Dogaru int ret; 254c78b9171SVlad Dogaru 255c78b9171SVlad Dogaru switch (chan->type) { 256c78b9171SVlad Dogaru case IIO_INCLI: 257c78b9171SVlad Dogaru if (val2 != 0 || val < 1 || val > 10) 258c78b9171SVlad Dogaru return -EINVAL; 259c78b9171SVlad Dogaru mutex_lock(&data->mutex); 260c78b9171SVlad Dogaru ret = mma9551_update_config_bits(data->client, 261c78b9171SVlad Dogaru MMA9551_APPID_TILT, 262c78b9171SVlad Dogaru MMA9551_TILT_CFG_REG, 263c78b9171SVlad Dogaru MMA9551_TILT_ANG_THRESH_MASK, 264c78b9171SVlad Dogaru val); 265c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 266c78b9171SVlad Dogaru return ret; 267c78b9171SVlad Dogaru default: 268c78b9171SVlad Dogaru return -EINVAL; 269c78b9171SVlad Dogaru } 270c78b9171SVlad Dogaru } 271c78b9171SVlad Dogaru 272c78b9171SVlad Dogaru static int mma9551_read_event_value(struct iio_dev *indio_dev, 273c78b9171SVlad Dogaru const struct iio_chan_spec *chan, 274c78b9171SVlad Dogaru enum iio_event_type type, 275c78b9171SVlad Dogaru enum iio_event_direction dir, 276c78b9171SVlad Dogaru enum iio_event_info info, 277c78b9171SVlad Dogaru int *val, int *val2) 278c78b9171SVlad Dogaru { 279c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 280c78b9171SVlad Dogaru int ret; 281c78b9171SVlad Dogaru u8 tmp; 282c78b9171SVlad Dogaru 283c78b9171SVlad Dogaru switch (chan->type) { 284c78b9171SVlad Dogaru case IIO_INCLI: 285c78b9171SVlad Dogaru mutex_lock(&data->mutex); 286c78b9171SVlad Dogaru ret = mma9551_read_config_byte(data->client, 287c78b9171SVlad Dogaru MMA9551_APPID_TILT, 288c78b9171SVlad Dogaru MMA9551_TILT_CFG_REG, &tmp); 289c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 290c78b9171SVlad Dogaru if (ret < 0) 291c78b9171SVlad Dogaru return ret; 292c78b9171SVlad Dogaru *val = tmp & MMA9551_TILT_ANG_THRESH_MASK; 293c78b9171SVlad Dogaru *val2 = 0; 294c78b9171SVlad Dogaru return IIO_VAL_INT; 295c78b9171SVlad Dogaru default: 296c78b9171SVlad Dogaru return -EINVAL; 297c78b9171SVlad Dogaru } 298c78b9171SVlad Dogaru } 299c78b9171SVlad Dogaru 300c78b9171SVlad Dogaru static const struct iio_event_spec mma9551_incli_event = { 301c78b9171SVlad Dogaru .type = IIO_EV_TYPE_ROC, 302c78b9171SVlad Dogaru .dir = IIO_EV_DIR_RISING, 303c78b9171SVlad Dogaru .mask_separate = BIT(IIO_EV_INFO_ENABLE), 304c78b9171SVlad Dogaru .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), 305c78b9171SVlad Dogaru }; 306c78b9171SVlad Dogaru 307c78b9171SVlad Dogaru #define MMA9551_INCLI_CHANNEL(axis) { \ 308c78b9171SVlad Dogaru .type = IIO_INCLI, \ 309c78b9171SVlad Dogaru .modified = 1, \ 310c78b9171SVlad Dogaru .channel2 = axis, \ 311c78b9171SVlad Dogaru .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ 312c78b9171SVlad Dogaru .event_spec = &mma9551_incli_event, \ 313c78b9171SVlad Dogaru .num_event_specs = 1, \ 314c78b9171SVlad Dogaru } 315c78b9171SVlad Dogaru 316c78b9171SVlad Dogaru static const struct iio_chan_spec mma9551_channels[] = { 317c78b9171SVlad Dogaru MMA9551_ACCEL_CHANNEL(IIO_MOD_X), 318c78b9171SVlad Dogaru MMA9551_ACCEL_CHANNEL(IIO_MOD_Y), 319c78b9171SVlad Dogaru MMA9551_ACCEL_CHANNEL(IIO_MOD_Z), 320c78b9171SVlad Dogaru 321c78b9171SVlad Dogaru MMA9551_INCLI_CHANNEL(IIO_MOD_X), 322c78b9171SVlad Dogaru MMA9551_INCLI_CHANNEL(IIO_MOD_Y), 323c78b9171SVlad Dogaru MMA9551_INCLI_CHANNEL(IIO_MOD_Z), 324c78b9171SVlad Dogaru }; 325c78b9171SVlad Dogaru 326c78b9171SVlad Dogaru static const struct iio_info mma9551_info = { 327c78b9171SVlad Dogaru .read_raw = mma9551_read_raw, 328c78b9171SVlad Dogaru .read_event_config = mma9551_read_event_config, 329c78b9171SVlad Dogaru .write_event_config = mma9551_write_event_config, 330c78b9171SVlad Dogaru .read_event_value = mma9551_read_event_value, 331c78b9171SVlad Dogaru .write_event_value = mma9551_write_event_value, 332c78b9171SVlad Dogaru }; 333c78b9171SVlad Dogaru 334c78b9171SVlad Dogaru static irqreturn_t mma9551_event_handler(int irq, void *private) 335c78b9171SVlad Dogaru { 336c78b9171SVlad Dogaru struct iio_dev *indio_dev = private; 337c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 338c78b9171SVlad Dogaru int i, ret, mma_axis = -1; 339c78b9171SVlad Dogaru u16 reg; 340c78b9171SVlad Dogaru u8 val; 341c78b9171SVlad Dogaru 342c78b9171SVlad Dogaru mutex_lock(&data->mutex); 343c78b9171SVlad Dogaru 344c78b9171SVlad Dogaru for (i = 0; i < 3; i++) 345c78b9171SVlad Dogaru if (irq == data->irqs[i]) { 346c78b9171SVlad Dogaru mma_axis = i; 347c78b9171SVlad Dogaru break; 348c78b9171SVlad Dogaru } 349c78b9171SVlad Dogaru 350c78b9171SVlad Dogaru if (mma_axis == -1) { 351c78b9171SVlad Dogaru /* IRQ was triggered on 4th line, which we don't use. */ 352c78b9171SVlad Dogaru dev_warn(&data->client->dev, 353c78b9171SVlad Dogaru "irq triggered on unused line %d\n", data->irqs[3]); 354c78b9171SVlad Dogaru goto out; 355c78b9171SVlad Dogaru } 356c78b9171SVlad Dogaru 357c78b9171SVlad Dogaru switch (mma_axis) { 358c78b9171SVlad Dogaru case mma9551_x: 359c78b9171SVlad Dogaru reg = MMA9551_TILT_YZ_ANG_REG; 360c78b9171SVlad Dogaru break; 361c78b9171SVlad Dogaru case mma9551_y: 362c78b9171SVlad Dogaru reg = MMA9551_TILT_XZ_ANG_REG; 363c78b9171SVlad Dogaru break; 364c78b9171SVlad Dogaru case mma9551_z: 365c78b9171SVlad Dogaru reg = MMA9551_TILT_XY_ANG_REG; 366c78b9171SVlad Dogaru break; 367c78b9171SVlad Dogaru } 368c78b9171SVlad Dogaru 369c78b9171SVlad Dogaru /* 370c78b9171SVlad Dogaru * Read the angle even though we don't use it, otherwise we 371c78b9171SVlad Dogaru * won't get any further interrupts. 372c78b9171SVlad Dogaru */ 373c78b9171SVlad Dogaru ret = mma9551_read_status_byte(data->client, MMA9551_APPID_TILT, 374c78b9171SVlad Dogaru reg, &val); 375c78b9171SVlad Dogaru if (ret < 0) { 376c78b9171SVlad Dogaru dev_err(&data->client->dev, 377c78b9171SVlad Dogaru "error %d reading tilt register in IRQ\n", ret); 378c78b9171SVlad Dogaru goto out; 379c78b9171SVlad Dogaru } 380c78b9171SVlad Dogaru 381c78b9171SVlad Dogaru iio_push_event(indio_dev, 382c78b9171SVlad Dogaru IIO_MOD_EVENT_CODE(IIO_INCLI, 0, (mma_axis + 1), 383c78b9171SVlad Dogaru IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING), 384bc2b7dabSGregor Boirie iio_get_time_ns(indio_dev)); 385c78b9171SVlad Dogaru 386c78b9171SVlad Dogaru out: 387c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 388c78b9171SVlad Dogaru 389c78b9171SVlad Dogaru return IRQ_HANDLED; 390c78b9171SVlad Dogaru } 391c78b9171SVlad Dogaru 392c78b9171SVlad Dogaru static int mma9551_init(struct mma9551_data *data) 393c78b9171SVlad Dogaru { 394c78b9171SVlad Dogaru int ret; 395c78b9171SVlad Dogaru 396c78b9171SVlad Dogaru ret = mma9551_read_version(data->client); 397c78b9171SVlad Dogaru if (ret) 398c78b9171SVlad Dogaru return ret; 399c78b9171SVlad Dogaru 4006da93a67SIrina Tirdea return mma9551_set_device_state(data->client, true); 401c78b9171SVlad Dogaru } 402c78b9171SVlad Dogaru 403c78b9171SVlad Dogaru static int mma9551_gpio_probe(struct iio_dev *indio_dev) 404c78b9171SVlad Dogaru { 405c78b9171SVlad Dogaru struct gpio_desc *gpio; 406c78b9171SVlad Dogaru int i, ret; 407c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 408c78b9171SVlad Dogaru struct device *dev = &data->client->dev; 409c78b9171SVlad Dogaru 410c78b9171SVlad Dogaru for (i = 0; i < MMA9551_GPIO_COUNT; i++) { 411ed3edc09SAndy Shevchenko gpio = devm_gpiod_get_index(dev, NULL, i, GPIOD_IN); 412c78b9171SVlad Dogaru if (IS_ERR(gpio)) { 413c78b9171SVlad Dogaru dev_err(dev, "acpi gpio get index failed\n"); 414c78b9171SVlad Dogaru return PTR_ERR(gpio); 415c78b9171SVlad Dogaru } 416c78b9171SVlad Dogaru 417debf6d84SRoberta Dobrescu ret = gpiod_to_irq(gpio); 418debf6d84SRoberta Dobrescu if (ret < 0) 419debf6d84SRoberta Dobrescu return ret; 420debf6d84SRoberta Dobrescu 421debf6d84SRoberta Dobrescu data->irqs[i] = ret; 422c78b9171SVlad Dogaru ret = devm_request_threaded_irq(dev, data->irqs[i], 423c78b9171SVlad Dogaru NULL, mma9551_event_handler, 424c78b9171SVlad Dogaru IRQF_TRIGGER_RISING | IRQF_ONESHOT, 425c78b9171SVlad Dogaru MMA9551_IRQ_NAME, indio_dev); 426c78b9171SVlad Dogaru if (ret < 0) { 427c78b9171SVlad Dogaru dev_err(dev, "request irq %d failed\n", data->irqs[i]); 428c78b9171SVlad Dogaru return ret; 429c78b9171SVlad Dogaru } 430c78b9171SVlad Dogaru 431c78b9171SVlad Dogaru dev_dbg(dev, "gpio resource, no:%d irq:%d\n", 432c78b9171SVlad Dogaru desc_to_gpio(gpio), data->irqs[i]); 433c78b9171SVlad Dogaru } 434c78b9171SVlad Dogaru 435c78b9171SVlad Dogaru return 0; 436c78b9171SVlad Dogaru } 437c78b9171SVlad Dogaru 438c78b9171SVlad Dogaru static const char *mma9551_match_acpi_device(struct device *dev) 439c78b9171SVlad Dogaru { 440c78b9171SVlad Dogaru const struct acpi_device_id *id; 441c78b9171SVlad Dogaru 442c78b9171SVlad Dogaru id = acpi_match_device(dev->driver->acpi_match_table, dev); 443c78b9171SVlad Dogaru if (!id) 444c78b9171SVlad Dogaru return NULL; 445c78b9171SVlad Dogaru 446c78b9171SVlad Dogaru return dev_name(dev); 447c78b9171SVlad Dogaru } 448c78b9171SVlad Dogaru 449c78b9171SVlad Dogaru static int mma9551_probe(struct i2c_client *client, 450c78b9171SVlad Dogaru const struct i2c_device_id *id) 451c78b9171SVlad Dogaru { 452c78b9171SVlad Dogaru struct mma9551_data *data; 453c78b9171SVlad Dogaru struct iio_dev *indio_dev; 454c78b9171SVlad Dogaru const char *name = NULL; 455c78b9171SVlad Dogaru int ret; 456c78b9171SVlad Dogaru 457c78b9171SVlad Dogaru indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 458c78b9171SVlad Dogaru if (!indio_dev) 459c78b9171SVlad Dogaru return -ENOMEM; 460c78b9171SVlad Dogaru 461c78b9171SVlad Dogaru data = iio_priv(indio_dev); 462c78b9171SVlad Dogaru i2c_set_clientdata(client, indio_dev); 463c78b9171SVlad Dogaru data->client = client; 464c78b9171SVlad Dogaru 465c78b9171SVlad Dogaru if (id) 466c78b9171SVlad Dogaru name = id->name; 467c78b9171SVlad Dogaru else if (ACPI_HANDLE(&client->dev)) 468c78b9171SVlad Dogaru name = mma9551_match_acpi_device(&client->dev); 469c78b9171SVlad Dogaru 470c78b9171SVlad Dogaru ret = mma9551_init(data); 471c78b9171SVlad Dogaru if (ret < 0) 472c78b9171SVlad Dogaru return ret; 473c78b9171SVlad Dogaru 474c78b9171SVlad Dogaru mutex_init(&data->mutex); 475c78b9171SVlad Dogaru 476c78b9171SVlad Dogaru indio_dev->channels = mma9551_channels; 477c78b9171SVlad Dogaru indio_dev->num_channels = ARRAY_SIZE(mma9551_channels); 478c78b9171SVlad Dogaru indio_dev->name = name; 479c78b9171SVlad Dogaru indio_dev->modes = INDIO_DIRECT_MODE; 480c78b9171SVlad Dogaru indio_dev->info = &mma9551_info; 481c78b9171SVlad Dogaru 482c78b9171SVlad Dogaru ret = mma9551_gpio_probe(indio_dev); 483c78b9171SVlad Dogaru if (ret < 0) 484c78b9171SVlad Dogaru goto out_poweroff; 485c78b9171SVlad Dogaru 4866da93a67SIrina Tirdea ret = pm_runtime_set_active(&client->dev); 4876da93a67SIrina Tirdea if (ret < 0) 4887d0ead5cSAdriana Reus goto out_poweroff; 4896da93a67SIrina Tirdea 4906da93a67SIrina Tirdea pm_runtime_enable(&client->dev); 4916da93a67SIrina Tirdea pm_runtime_set_autosuspend_delay(&client->dev, 4926da93a67SIrina Tirdea MMA9551_AUTO_SUSPEND_DELAY_MS); 4936da93a67SIrina Tirdea pm_runtime_use_autosuspend(&client->dev); 4946da93a67SIrina Tirdea 4957d0ead5cSAdriana Reus ret = iio_device_register(indio_dev); 4967d0ead5cSAdriana Reus if (ret < 0) { 4977d0ead5cSAdriana Reus dev_err(&client->dev, "unable to register iio device\n"); 4987d0ead5cSAdriana Reus goto out_poweroff; 4997d0ead5cSAdriana Reus } 5007d0ead5cSAdriana Reus 501c78b9171SVlad Dogaru return 0; 502c78b9171SVlad Dogaru 503c78b9171SVlad Dogaru out_poweroff: 504c78b9171SVlad Dogaru mma9551_set_device_state(client, false); 505c78b9171SVlad Dogaru 506c78b9171SVlad Dogaru return ret; 507c78b9171SVlad Dogaru } 508c78b9171SVlad Dogaru 509c78b9171SVlad Dogaru static int mma9551_remove(struct i2c_client *client) 510c78b9171SVlad Dogaru { 511c78b9171SVlad Dogaru struct iio_dev *indio_dev = i2c_get_clientdata(client); 512c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 513c78b9171SVlad Dogaru 5147d0ead5cSAdriana Reus iio_device_unregister(indio_dev); 5157d0ead5cSAdriana Reus 5166da93a67SIrina Tirdea pm_runtime_disable(&client->dev); 5176da93a67SIrina Tirdea pm_runtime_set_suspended(&client->dev); 5186da93a67SIrina Tirdea 519c78b9171SVlad Dogaru mutex_lock(&data->mutex); 520c78b9171SVlad Dogaru mma9551_set_device_state(data->client, false); 521c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 522c78b9171SVlad Dogaru 523c78b9171SVlad Dogaru return 0; 524c78b9171SVlad Dogaru } 525c78b9171SVlad Dogaru 5266da93a67SIrina Tirdea static int mma9551_runtime_suspend(struct device *dev) 5276da93a67SIrina Tirdea { 5286da93a67SIrina Tirdea struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 5296da93a67SIrina Tirdea struct mma9551_data *data = iio_priv(indio_dev); 5306da93a67SIrina Tirdea int ret; 5316da93a67SIrina Tirdea 5326da93a67SIrina Tirdea mutex_lock(&data->mutex); 5336da93a67SIrina Tirdea ret = mma9551_set_device_state(data->client, false); 5346da93a67SIrina Tirdea mutex_unlock(&data->mutex); 5356da93a67SIrina Tirdea if (ret < 0) { 5366da93a67SIrina Tirdea dev_err(&data->client->dev, "powering off device failed\n"); 5376da93a67SIrina Tirdea return -EAGAIN; 5386da93a67SIrina Tirdea } 5396da93a67SIrina Tirdea 5406da93a67SIrina Tirdea return 0; 5416da93a67SIrina Tirdea } 5426da93a67SIrina Tirdea 5436da93a67SIrina Tirdea static int mma9551_runtime_resume(struct device *dev) 5446da93a67SIrina Tirdea { 5456da93a67SIrina Tirdea struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 5466da93a67SIrina Tirdea struct mma9551_data *data = iio_priv(indio_dev); 5476da93a67SIrina Tirdea int ret; 5486da93a67SIrina Tirdea 5496da93a67SIrina Tirdea ret = mma9551_set_device_state(data->client, true); 5506da93a67SIrina Tirdea if (ret < 0) 5516da93a67SIrina Tirdea return ret; 5526da93a67SIrina Tirdea 5536da93a67SIrina Tirdea mma9551_sleep(MMA9551_DEFAULT_SAMPLE_RATE); 5546da93a67SIrina Tirdea 5556da93a67SIrina Tirdea return 0; 5566da93a67SIrina Tirdea } 5576da93a67SIrina Tirdea 558c78b9171SVlad Dogaru static int mma9551_suspend(struct device *dev) 559c78b9171SVlad Dogaru { 560c78b9171SVlad Dogaru struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 561c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 5626da93a67SIrina Tirdea int ret; 563c78b9171SVlad Dogaru 564c78b9171SVlad Dogaru mutex_lock(&data->mutex); 5656da93a67SIrina Tirdea ret = mma9551_set_device_state(data->client, false); 566c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 567c78b9171SVlad Dogaru 5686da93a67SIrina Tirdea return ret; 569c78b9171SVlad Dogaru } 570c78b9171SVlad Dogaru 571c78b9171SVlad Dogaru static int mma9551_resume(struct device *dev) 572c78b9171SVlad Dogaru { 573c78b9171SVlad Dogaru struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 574c78b9171SVlad Dogaru struct mma9551_data *data = iio_priv(indio_dev); 5756da93a67SIrina Tirdea int ret; 576c78b9171SVlad Dogaru 577c78b9171SVlad Dogaru mutex_lock(&data->mutex); 5786da93a67SIrina Tirdea ret = mma9551_set_device_state(data->client, true); 579c78b9171SVlad Dogaru mutex_unlock(&data->mutex); 580c78b9171SVlad Dogaru 5816da93a67SIrina Tirdea return ret; 582c78b9171SVlad Dogaru } 583c78b9171SVlad Dogaru 584c78b9171SVlad Dogaru static const struct dev_pm_ops mma9551_pm_ops = { 585*81e566f9SJonathan Cameron SYSTEM_SLEEP_PM_OPS(mma9551_suspend, mma9551_resume) 586*81e566f9SJonathan Cameron RUNTIME_PM_OPS(mma9551_runtime_suspend, mma9551_runtime_resume, NULL) 587c78b9171SVlad Dogaru }; 588c78b9171SVlad Dogaru 589c78b9171SVlad Dogaru static const struct acpi_device_id mma9551_acpi_match[] = { 590c78b9171SVlad Dogaru {"MMA9551", 0}, 591c78b9171SVlad Dogaru {}, 592c78b9171SVlad Dogaru }; 593c78b9171SVlad Dogaru 594c78b9171SVlad Dogaru MODULE_DEVICE_TABLE(acpi, mma9551_acpi_match); 595c78b9171SVlad Dogaru 596c78b9171SVlad Dogaru static const struct i2c_device_id mma9551_id[] = { 597c78b9171SVlad Dogaru {"mma9551", 0}, 598c78b9171SVlad Dogaru {} 599c78b9171SVlad Dogaru }; 600c78b9171SVlad Dogaru 601c78b9171SVlad Dogaru MODULE_DEVICE_TABLE(i2c, mma9551_id); 602c78b9171SVlad Dogaru 603c78b9171SVlad Dogaru static struct i2c_driver mma9551_driver = { 604c78b9171SVlad Dogaru .driver = { 605c78b9171SVlad Dogaru .name = MMA9551_DRV_NAME, 606c78b9171SVlad Dogaru .acpi_match_table = ACPI_PTR(mma9551_acpi_match), 607*81e566f9SJonathan Cameron .pm = pm_ptr(&mma9551_pm_ops), 608c78b9171SVlad Dogaru }, 609c78b9171SVlad Dogaru .probe = mma9551_probe, 610c78b9171SVlad Dogaru .remove = mma9551_remove, 611c78b9171SVlad Dogaru .id_table = mma9551_id, 612c78b9171SVlad Dogaru }; 613c78b9171SVlad Dogaru 614c78b9171SVlad Dogaru module_i2c_driver(mma9551_driver); 615c78b9171SVlad Dogaru 616c78b9171SVlad Dogaru MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>"); 617c78b9171SVlad Dogaru MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>"); 618c78b9171SVlad Dogaru MODULE_LICENSE("GPL v2"); 619c78b9171SVlad Dogaru MODULE_DESCRIPTION("MMA9551L motion-sensing platform driver"); 6204205a215SJonathan Cameron MODULE_IMPORT_NS(IIO_MMA9551); 621