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