linux/drivers/iio/accel/mma9551_core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Common code for Freescale MMA955x Intelligent Sensor Platform drivers
   4 * Copyright (c) 2014, Intel Corporation.
   5 */
   6
   7#include <linux/module.h>
   8#include <linux/i2c.h>
   9#include <linux/delay.h>
  10#include <linux/iio/iio.h>
  11#include <linux/pm_runtime.h>
  12#include "mma9551_core.h"
  13
  14/* Command masks for mailbox write command */
  15#define MMA9551_CMD_READ_VERSION_INFO   0x00
  16#define MMA9551_CMD_READ_CONFIG         0x10
  17#define MMA9551_CMD_WRITE_CONFIG        0x20
  18#define MMA9551_CMD_READ_STATUS         0x30
  19
  20/* Mailbox read command */
  21#define MMA9551_RESPONSE_COCO           BIT(7)
  22
  23/* Error-Status codes returned in mailbox read command */
  24#define MMA9551_MCI_ERROR_NONE                  0x00
  25#define MMA9551_MCI_ERROR_PARAM                 0x04
  26#define MMA9551_MCI_INVALID_COUNT               0x19
  27#define MMA9551_MCI_ERROR_COMMAND               0x1C
  28#define MMA9551_MCI_ERROR_INVALID_LENGTH        0x21
  29#define MMA9551_MCI_ERROR_FIFO_BUSY             0x22
  30#define MMA9551_MCI_ERROR_FIFO_ALLOCATED        0x23
  31#define MMA9551_MCI_ERROR_FIFO_OVERSIZE         0x24
  32
  33/* GPIO Application */
  34#define MMA9551_GPIO_POL_MSB            0x08
  35#define MMA9551_GPIO_POL_LSB            0x09
  36
  37/* Sleep/Wake application */
  38#define MMA9551_SLEEP_CFG               0x06
  39#define MMA9551_SLEEP_CFG_SNCEN         BIT(0)
  40#define MMA9551_SLEEP_CFG_FLEEN         BIT(1)
  41#define MMA9551_SLEEP_CFG_SCHEN         BIT(2)
  42
  43/* AFE application */
  44#define MMA9551_AFE_X_ACCEL_REG         0x00
  45#define MMA9551_AFE_Y_ACCEL_REG         0x02
  46#define MMA9551_AFE_Z_ACCEL_REG         0x04
  47
  48/* Reset/Suspend/Clear application */
  49#define MMA9551_RSC_RESET               0x00
  50#define MMA9551_RSC_OFFSET(mask)        (3 - (ffs(mask) - 1) / 8)
  51#define MMA9551_RSC_VAL(mask)           (mask >> (((ffs(mask) - 1) / 8) * 8))
  52
  53/*
  54 * A response is composed of:
  55 * - control registers: MB0-3
  56 * - data registers: MB4-31
  57 *
  58 * A request is composed of:
  59 * - mbox to write to (always 0)
  60 * - control registers: MB1-4
  61 * - data registers: MB5-31
  62 */
  63#define MMA9551_MAILBOX_CTRL_REGS       4
  64#define MMA9551_MAX_MAILBOX_DATA_REGS   28
  65#define MMA9551_MAILBOX_REGS            32
  66
  67#define MMA9551_I2C_READ_RETRIES        5
  68#define MMA9551_I2C_READ_DELAY  50      /* us */
  69
  70struct mma9551_mbox_request {
  71        u8 start_mbox;          /* Always 0. */
  72        u8 app_id;
  73        /*
  74         * See Section 5.3.1 of the MMA955xL Software Reference Manual.
  75         *
  76         * Bit 7: reserved, always 0
  77         * Bits 6-4: command
  78         * Bits 3-0: upper bits of register offset
  79         */
  80        u8 cmd_off;
  81        u8 lower_off;
  82        u8 nbytes;
  83        u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS - 1];
  84} __packed;
  85
  86struct mma9551_mbox_response {
  87        u8 app_id;
  88        /*
  89         * See Section 5.3.3 of the MMA955xL Software Reference Manual.
  90         *
  91         * Bit 7: COCO
  92         * Bits 6-0: Error code.
  93         */
  94        u8 coco_err;
  95        u8 nbytes;
  96        u8 req_bytes;
  97        u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS];
  98} __packed;
  99
 100struct mma9551_version_info {
 101        __be32 device_id;
 102        u8 rom_version[2];
 103        u8 fw_version[2];
 104        u8 hw_version[2];
 105        u8 fw_build[2];
 106};
 107
 108static int mma9551_transfer(struct i2c_client *client,
 109                            u8 app_id, u8 command, u16 offset,
 110                            u8 *inbytes, int num_inbytes,
 111                            u8 *outbytes, int num_outbytes)
 112{
 113        struct mma9551_mbox_request req;
 114        struct mma9551_mbox_response rsp;
 115        struct i2c_msg in, out;
 116        u8 req_len, err_code;
 117        int ret, retries;
 118
 119        if (offset >= 1 << 12) {
 120                dev_err(&client->dev, "register offset too large\n");
 121                return -EINVAL;
 122        }
 123
 124        req_len = 1 + MMA9551_MAILBOX_CTRL_REGS + num_inbytes;
 125        req.start_mbox = 0;
 126        req.app_id = app_id;
 127        req.cmd_off = command | (offset >> 8);
 128        req.lower_off = offset;
 129
 130        if (command == MMA9551_CMD_WRITE_CONFIG)
 131                req.nbytes = num_inbytes;
 132        else
 133                req.nbytes = num_outbytes;
 134        if (num_inbytes)
 135                memcpy(req.buf, inbytes, num_inbytes);
 136
 137        out.addr = client->addr;
 138        out.flags = 0;
 139        out.len = req_len;
 140        out.buf = (u8 *)&req;
 141
 142        ret = i2c_transfer(client->adapter, &out, 1);
 143        if (ret < 0) {
 144                dev_err(&client->dev, "i2c write failed\n");
 145                return ret;
 146        }
 147
 148        retries = MMA9551_I2C_READ_RETRIES;
 149        do {
 150                udelay(MMA9551_I2C_READ_DELAY);
 151
 152                in.addr = client->addr;
 153                in.flags = I2C_M_RD;
 154                in.len = sizeof(rsp);
 155                in.buf = (u8 *)&rsp;
 156
 157                ret = i2c_transfer(client->adapter, &in, 1);
 158                if (ret < 0) {
 159                        dev_err(&client->dev, "i2c read failed\n");
 160                        return ret;
 161                }
 162
 163                if (rsp.coco_err & MMA9551_RESPONSE_COCO)
 164                        break;
 165        } while (--retries > 0);
 166
 167        if (retries == 0) {
 168                dev_err(&client->dev,
 169                        "timed out while waiting for command response\n");
 170                return -ETIMEDOUT;
 171        }
 172
 173        if (rsp.app_id != app_id) {
 174                dev_err(&client->dev,
 175                        "app_id mismatch in response got %02x expected %02x\n",
 176                        rsp.app_id, app_id);
 177                return -EINVAL;
 178        }
 179
 180        err_code = rsp.coco_err & ~MMA9551_RESPONSE_COCO;
 181        if (err_code != MMA9551_MCI_ERROR_NONE) {
 182                dev_err(&client->dev, "read returned error %x\n", err_code);
 183                return -EINVAL;
 184        }
 185
 186        if (rsp.nbytes != rsp.req_bytes) {
 187                dev_err(&client->dev,
 188                        "output length mismatch got %d expected %d\n",
 189                        rsp.nbytes, rsp.req_bytes);
 190                return -EINVAL;
 191        }
 192
 193        if (num_outbytes)
 194                memcpy(outbytes, rsp.buf, num_outbytes);
 195
 196        return 0;
 197}
 198
 199/**
 200 * mma9551_read_config_byte() - read 1 configuration byte
 201 * @client:     I2C client
 202 * @app_id:     Application ID
 203 * @reg:        Application register
 204 * @val:        Pointer to store value read
 205 *
 206 * Read one configuration byte from the device using MMA955xL command format.
 207 * Commands to the MMA955xL platform consist of a write followed
 208 * by one or more reads.
 209 *
 210 * Locking note: This function must be called with the device lock held.
 211 * Locking is not handled inside the function. Callers should ensure they
 212 * serialize access to the HW.
 213 *
 214 * Returns: 0 on success, negative value on failure.
 215 */
 216int mma9551_read_config_byte(struct i2c_client *client, u8 app_id,
 217                             u16 reg, u8 *val)
 218{
 219        return mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG,
 220                                reg, NULL, 0, val, 1);
 221}
 222EXPORT_SYMBOL(mma9551_read_config_byte);
 223
 224/**
 225 * mma9551_write_config_byte() - write 1 configuration byte
 226 * @client:     I2C client
 227 * @app_id:     Application ID
 228 * @reg:        Application register
 229 * @val:        Value to write
 230 *
 231 * Write one configuration byte from the device using MMA955xL command format.
 232 * Commands to the MMA955xL platform consist of a write followed by one or
 233 * more reads.
 234 *
 235 * Locking note: This function must be called with the device lock held.
 236 * Locking is not handled inside the function. Callers should ensure they
 237 * serialize access to the HW.
 238 *
 239 * Returns: 0 on success, negative value on failure.
 240 */
 241int mma9551_write_config_byte(struct i2c_client *client, u8 app_id,
 242                              u16 reg, u8 val)
 243{
 244        return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg,
 245                                &val, 1, NULL, 0);
 246}
 247EXPORT_SYMBOL(mma9551_write_config_byte);
 248
 249/**
 250 * mma9551_read_status_byte() - read 1 status byte
 251 * @client:     I2C client
 252 * @app_id:     Application ID
 253 * @reg:        Application register
 254 * @val:        Pointer to store value read
 255 *
 256 * Read one status byte from the device using MMA955xL command format.
 257 * Commands to the MMA955xL platform consist of a write followed by one or
 258 * more reads.
 259 *
 260 * Locking note: This function must be called with the device lock held.
 261 * Locking is not handled inside the function. Callers should ensure they
 262 * serialize access to the HW.
 263 *
 264 * Returns: 0 on success, negative value on failure.
 265 */
 266int mma9551_read_status_byte(struct i2c_client *client, u8 app_id,
 267                             u16 reg, u8 *val)
 268{
 269        return mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS,
 270                                reg, NULL, 0, val, 1);
 271}
 272EXPORT_SYMBOL(mma9551_read_status_byte);
 273
 274/**
 275 * mma9551_read_config_word() - read 1 config word
 276 * @client:     I2C client
 277 * @app_id:     Application ID
 278 * @reg:        Application register
 279 * @val:        Pointer to store value read
 280 *
 281 * Read one configuration word from the device using MMA955xL command format.
 282 * Commands to the MMA955xL platform consist of a write followed by one or
 283 * more reads.
 284 *
 285 * Locking note: This function must be called with the device lock held.
 286 * Locking is not handled inside the function. Callers should ensure they
 287 * serialize access to the HW.
 288 *
 289 * Returns: 0 on success, negative value on failure.
 290 */
 291int mma9551_read_config_word(struct i2c_client *client, u8 app_id,
 292                             u16 reg, u16 *val)
 293{
 294        int ret;
 295        __be16 v;
 296
 297        ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG,
 298                               reg, NULL, 0, (u8 *)&v, 2);
 299        *val = be16_to_cpu(v);
 300
 301        return ret;
 302}
 303EXPORT_SYMBOL(mma9551_read_config_word);
 304
 305/**
 306 * mma9551_write_config_word() - write 1 config word
 307 * @client:     I2C client
 308 * @app_id:     Application ID
 309 * @reg:        Application register
 310 * @val:        Value to write
 311 *
 312 * Write one configuration word from the device using MMA955xL command format.
 313 * Commands to the MMA955xL platform consist of a write followed by one or
 314 * more reads.
 315 *
 316 * Locking note: This function must be called with the device lock held.
 317 * Locking is not handled inside the function. Callers should ensure they
 318 * serialize access to the HW.
 319 *
 320 * Returns: 0 on success, negative value on failure.
 321 */
 322int mma9551_write_config_word(struct i2c_client *client, u8 app_id,
 323                              u16 reg, u16 val)
 324{
 325        __be16 v = cpu_to_be16(val);
 326
 327        return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg,
 328                                (u8 *)&v, 2, NULL, 0);
 329}
 330EXPORT_SYMBOL(mma9551_write_config_word);
 331
 332/**
 333 * mma9551_read_status_word() - read 1 status word
 334 * @client:     I2C client
 335 * @app_id:     Application ID
 336 * @reg:        Application register
 337 * @val:        Pointer to store value read
 338 *
 339 * Read one status word from the device using MMA955xL command format.
 340 * Commands to the MMA955xL platform consist of a write followed by one or
 341 * more reads.
 342 *
 343 * Locking note: This function must be called with the device lock held.
 344 * Locking is not handled inside the function. Callers should ensure they
 345 * serialize access to the HW.
 346 *
 347 * Returns: 0 on success, negative value on failure.
 348 */
 349int mma9551_read_status_word(struct i2c_client *client, u8 app_id,
 350                             u16 reg, u16 *val)
 351{
 352        int ret;
 353        __be16 v;
 354
 355        ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS,
 356                               reg, NULL, 0, (u8 *)&v, 2);
 357        *val = be16_to_cpu(v);
 358
 359        return ret;
 360}
 361EXPORT_SYMBOL(mma9551_read_status_word);
 362
 363/**
 364 * mma9551_read_config_words() - read multiple config words
 365 * @client:     I2C client
 366 * @app_id:     Application ID
 367 * @reg:        Application register
 368 * @len:        Length of array to read (in words)
 369 * @buf:        Array of words to read
 370 *
 371 * Read multiple configuration registers (word-sized registers).
 372 *
 373 * Locking note: This function must be called with the device lock held.
 374 * Locking is not handled inside the function. Callers should ensure they
 375 * serialize access to the HW.
 376 *
 377 * Returns: 0 on success, negative value on failure.
 378 */
 379int mma9551_read_config_words(struct i2c_client *client, u8 app_id,
 380                              u16 reg, u8 len, u16 *buf)
 381{
 382        int ret, i;
 383        __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS / 2];
 384
 385        if (len > ARRAY_SIZE(be_buf)) {
 386                dev_err(&client->dev, "Invalid buffer size %d\n", len);
 387                return -EINVAL;
 388        }
 389
 390        ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG,
 391                               reg, NULL, 0, (u8 *)be_buf, len * sizeof(u16));
 392        if (ret < 0)
 393                return ret;
 394
 395        for (i = 0; i < len; i++)
 396                buf[i] = be16_to_cpu(be_buf[i]);
 397
 398        return 0;
 399}
 400EXPORT_SYMBOL(mma9551_read_config_words);
 401
 402/**
 403 * mma9551_read_status_words() - read multiple status words
 404 * @client:     I2C client
 405 * @app_id:     Application ID
 406 * @reg:        Application register
 407 * @len:        Length of array to read (in words)
 408 * @buf:        Array of words to read
 409 *
 410 * Read multiple status registers (word-sized registers).
 411 *
 412 * Locking note: This function must be called with the device lock held.
 413 * Locking is not handled inside the function. Callers should ensure they
 414 * serialize access to the HW.
 415 *
 416 * Returns: 0 on success, negative value on failure.
 417 */
 418int mma9551_read_status_words(struct i2c_client *client, u8 app_id,
 419                              u16 reg, u8 len, u16 *buf)
 420{
 421        int ret, i;
 422        __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS / 2];
 423
 424        if (len > ARRAY_SIZE(be_buf)) {
 425                dev_err(&client->dev, "Invalid buffer size %d\n", len);
 426                return -EINVAL;
 427        }
 428
 429        ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS,
 430                               reg, NULL, 0, (u8 *)be_buf, len * sizeof(u16));
 431        if (ret < 0)
 432                return ret;
 433
 434        for (i = 0; i < len; i++)
 435                buf[i] = be16_to_cpu(be_buf[i]);
 436
 437        return 0;
 438}
 439EXPORT_SYMBOL(mma9551_read_status_words);
 440
 441/**
 442 * mma9551_write_config_words() - write multiple config words
 443 * @client:     I2C client
 444 * @app_id:     Application ID
 445 * @reg:        Application register
 446 * @len:        Length of array to write (in words)
 447 * @buf:        Array of words to write
 448 *
 449 * Write multiple configuration registers (word-sized registers).
 450 *
 451 * Locking note: This function must be called with the device lock held.
 452 * Locking is not handled inside the function. Callers should ensure they
 453 * serialize access to the HW.
 454 *
 455 * Returns: 0 on success, negative value on failure.
 456 */
 457int mma9551_write_config_words(struct i2c_client *client, u8 app_id,
 458                               u16 reg, u8 len, u16 *buf)
 459{
 460        int i;
 461        __be16 be_buf[(MMA9551_MAX_MAILBOX_DATA_REGS - 1) / 2];
 462
 463        if (len > ARRAY_SIZE(be_buf)) {
 464                dev_err(&client->dev, "Invalid buffer size %d\n", len);
 465                return -EINVAL;
 466        }
 467
 468        for (i = 0; i < len; i++)
 469                be_buf[i] = cpu_to_be16(buf[i]);
 470
 471        return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG,
 472                                reg, (u8 *)be_buf, len * sizeof(u16), NULL, 0);
 473}
 474EXPORT_SYMBOL(mma9551_write_config_words);
 475
 476/**
 477 * mma9551_update_config_bits() - update bits in register
 478 * @client:     I2C client
 479 * @app_id:     Application ID
 480 * @reg:        Application register
 481 * @mask:       Mask for the bits to update
 482 * @val:        Value of the bits to update
 483 *
 484 * Update bits in the given register using a bit mask.
 485 *
 486 * Locking note: This function must be called with the device lock held.
 487 * Locking is not handled inside the function. Callers should ensure they
 488 * serialize access to the HW.
 489 *
 490 * Returns: 0 on success, negative value on failure.
 491 */
 492int mma9551_update_config_bits(struct i2c_client *client, u8 app_id,
 493                               u16 reg, u8 mask, u8 val)
 494{
 495        int ret;
 496        u8 tmp, orig;
 497
 498        ret = mma9551_read_config_byte(client, app_id, reg, &orig);
 499        if (ret < 0)
 500                return ret;
 501
 502        tmp = orig & ~mask;
 503        tmp |= val & mask;
 504
 505        if (tmp == orig)
 506                return 0;
 507
 508        return mma9551_write_config_byte(client, app_id, reg, tmp);
 509}
 510EXPORT_SYMBOL(mma9551_update_config_bits);
 511
 512/**
 513 * mma9551_gpio_config() - configure gpio
 514 * @client:     I2C client
 515 * @pin:        GPIO pin to configure
 516 * @app_id:     Application ID
 517 * @bitnum:     Bit number of status register being assigned to the GPIO pin.
 518 * @polarity:   The polarity parameter is described in section 6.2.2, page 66,
 519 *              of the Software Reference Manual.  Basically, polarity=0 means
 520 *              the interrupt line has the same value as the selected bit,
 521 *              while polarity=1 means the line is inverted.
 522 *
 523 * Assign a bit from an application’s status register to a specific GPIO pin.
 524 *
 525 * Locking note: This function must be called with the device lock held.
 526 * Locking is not handled inside the function. Callers should ensure they
 527 * serialize access to the HW.
 528 *
 529 * Returns: 0 on success, negative value on failure.
 530 */
 531int mma9551_gpio_config(struct i2c_client *client, enum mma9551_gpio_pin pin,
 532                        u8 app_id, u8 bitnum, int polarity)
 533{
 534        u8 reg, pol_mask, pol_val;
 535        int ret;
 536
 537        if (pin > mma9551_gpio_max) {
 538                dev_err(&client->dev, "bad GPIO pin\n");
 539                return -EINVAL;
 540        }
 541
 542        /*
 543         * Pin 6 is configured by regs 0x00 and 0x01, pin 7 by 0x02 and
 544         * 0x03, and so on.
 545         */
 546        reg = pin * 2;
 547
 548        ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO,
 549                                        reg, app_id);
 550        if (ret < 0) {
 551                dev_err(&client->dev, "error setting GPIO app_id\n");
 552                return ret;
 553        }
 554
 555        ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO,
 556                                        reg + 1, bitnum);
 557        if (ret < 0) {
 558                dev_err(&client->dev, "error setting GPIO bit number\n");
 559                return ret;
 560        }
 561
 562        switch (pin) {
 563        case mma9551_gpio6:
 564                reg = MMA9551_GPIO_POL_LSB;
 565                pol_mask = 1 << 6;
 566                break;
 567        case mma9551_gpio7:
 568                reg = MMA9551_GPIO_POL_LSB;
 569                pol_mask = 1 << 7;
 570                break;
 571        case mma9551_gpio8:
 572                reg = MMA9551_GPIO_POL_MSB;
 573                pol_mask = 1 << 0;
 574                break;
 575        case mma9551_gpio9:
 576                reg = MMA9551_GPIO_POL_MSB;
 577                pol_mask = 1 << 1;
 578                break;
 579        }
 580        pol_val = polarity ? pol_mask : 0;
 581
 582        ret = mma9551_update_config_bits(client, MMA9551_APPID_GPIO, reg,
 583                                         pol_mask, pol_val);
 584        if (ret < 0)
 585                dev_err(&client->dev, "error setting GPIO polarity\n");
 586
 587        return ret;
 588}
 589EXPORT_SYMBOL(mma9551_gpio_config);
 590
 591/**
 592 * mma9551_read_version() - read device version information
 593 * @client:     I2C client
 594 *
 595 * Read version information and print device id and firmware version.
 596 *
 597 * Locking note: This function must be called with the device lock held.
 598 * Locking is not handled inside the function. Callers should ensure they
 599 * serialize access to the HW.
 600 *
 601 * Returns: 0 on success, negative value on failure.
 602 */
 603int mma9551_read_version(struct i2c_client *client)
 604{
 605        struct mma9551_version_info info;
 606        int ret;
 607
 608        ret = mma9551_transfer(client, MMA9551_APPID_VERSION, 0x00, 0x00,
 609                               NULL, 0, (u8 *)&info, sizeof(info));
 610        if (ret < 0)
 611                return ret;
 612
 613        dev_info(&client->dev, "device ID 0x%x, firmware version %02x.%02x\n",
 614                 be32_to_cpu(info.device_id), info.fw_version[0],
 615                 info.fw_version[1]);
 616
 617        return 0;
 618}
 619EXPORT_SYMBOL(mma9551_read_version);
 620
 621/**
 622 * mma9551_set_device_state() - sets HW power mode
 623 * @client:     I2C client
 624 * @enable:     Use true to power on device, false to cause the device
 625 *              to enter sleep.
 626 *
 627 * Set power on/off for device using the Sleep/Wake Application.
 628 * When enable is true, power on chip and enable doze mode.
 629 * When enable is false, enter sleep mode (device remains in the
 630 * lowest-power mode).
 631 *
 632 * Locking note: This function must be called with the device lock held.
 633 * Locking is not handled inside the function. Callers should ensure they
 634 * serialize access to the HW.
 635 *
 636 * Returns: 0 on success, negative value on failure.
 637 */
 638int mma9551_set_device_state(struct i2c_client *client, bool enable)
 639{
 640        return mma9551_update_config_bits(client, MMA9551_APPID_SLEEP_WAKE,
 641                                          MMA9551_SLEEP_CFG,
 642                                          MMA9551_SLEEP_CFG_SNCEN |
 643                                          MMA9551_SLEEP_CFG_FLEEN |
 644                                          MMA9551_SLEEP_CFG_SCHEN,
 645                                          enable ? MMA9551_SLEEP_CFG_SCHEN |
 646                                          MMA9551_SLEEP_CFG_FLEEN :
 647                                          MMA9551_SLEEP_CFG_SNCEN);
 648}
 649EXPORT_SYMBOL(mma9551_set_device_state);
 650
 651/**
 652 * mma9551_set_power_state() - sets runtime PM state
 653 * @client:     I2C client
 654 * @on:         Use true to power on device, false to power off
 655 *
 656 * Resume or suspend the device using Runtime PM.
 657 * The device will suspend after the autosuspend delay.
 658 *
 659 * Returns: 0 on success, negative value on failure.
 660 */
 661int mma9551_set_power_state(struct i2c_client *client, bool on)
 662{
 663#ifdef CONFIG_PM
 664        int ret;
 665
 666        if (on)
 667                ret = pm_runtime_resume_and_get(&client->dev);
 668        else {
 669                pm_runtime_mark_last_busy(&client->dev);
 670                ret = pm_runtime_put_autosuspend(&client->dev);
 671        }
 672
 673        if (ret < 0) {
 674                dev_err(&client->dev,
 675                        "failed to change power state to %d\n", on);
 676
 677                return ret;
 678        }
 679#endif
 680
 681        return 0;
 682}
 683EXPORT_SYMBOL(mma9551_set_power_state);
 684
 685/**
 686 * mma9551_sleep() - sleep
 687 * @freq:       Application frequency
 688 *
 689 * Firmware applications run at a certain frequency on the
 690 * device. Sleep for one application cycle to make sure the
 691 * application had time to run once and initialize set values.
 692 */
 693void mma9551_sleep(int freq)
 694{
 695        int sleep_val = 1000 / freq;
 696
 697        if (sleep_val < 20)
 698                usleep_range(sleep_val * 1000, 20000);
 699        else
 700                msleep_interruptible(sleep_val);
 701}
 702EXPORT_SYMBOL(mma9551_sleep);
 703
 704/**
 705 * mma9551_read_accel_chan() - read accelerometer channel
 706 * @client:     I2C client
 707 * @chan:       IIO channel
 708 * @val:        Pointer to the accelerometer value read
 709 * @val2:       Unused
 710 *
 711 * Read accelerometer value for the specified channel.
 712 *
 713 * Locking note: This function must be called with the device lock held.
 714 * Locking is not handled inside the function. Callers should ensure they
 715 * serialize access to the HW.
 716 *
 717 * Returns: IIO_VAL_INT on success, negative value on failure.
 718 */
 719int mma9551_read_accel_chan(struct i2c_client *client,
 720                            const struct iio_chan_spec *chan,
 721                            int *val, int *val2)
 722{
 723        u16 reg_addr;
 724        s16 raw_accel;
 725        int ret;
 726
 727        switch (chan->channel2) {
 728        case IIO_MOD_X:
 729                reg_addr = MMA9551_AFE_X_ACCEL_REG;
 730                break;
 731        case IIO_MOD_Y:
 732                reg_addr = MMA9551_AFE_Y_ACCEL_REG;
 733                break;
 734        case IIO_MOD_Z:
 735                reg_addr = MMA9551_AFE_Z_ACCEL_REG;
 736                break;
 737        default:
 738                return -EINVAL;
 739        }
 740
 741        ret = mma9551_set_power_state(client, true);
 742        if (ret < 0)
 743                return ret;
 744
 745        ret = mma9551_read_status_word(client, MMA9551_APPID_AFE,
 746                                       reg_addr, &raw_accel);
 747        if (ret < 0)
 748                goto out_poweroff;
 749
 750        *val = raw_accel;
 751
 752        ret = IIO_VAL_INT;
 753
 754out_poweroff:
 755        mma9551_set_power_state(client, false);
 756        return ret;
 757}
 758EXPORT_SYMBOL(mma9551_read_accel_chan);
 759
 760/**
 761 * mma9551_read_accel_scale() - read accelerometer scale
 762 * @val:        Pointer to the accelerometer scale (int value)
 763 * @val2:       Pointer to the accelerometer scale (micro value)
 764 *
 765 * Read accelerometer scale.
 766 *
 767 * Returns: IIO_VAL_INT_PLUS_MICRO.
 768 */
 769int mma9551_read_accel_scale(int *val, int *val2)
 770{
 771        *val = 0;
 772        *val2 = 2440;
 773
 774        return IIO_VAL_INT_PLUS_MICRO;
 775}
 776EXPORT_SYMBOL(mma9551_read_accel_scale);
 777
 778/**
 779 * mma9551_app_reset() - reset application
 780 * @client:     I2C client
 781 * @app_mask:   Application to reset
 782 *
 783 * Reset the given application (using the Reset/Suspend/Clear
 784 * Control Application)
 785 *
 786 * Returns: 0 on success, negative value on failure.
 787 */
 788int mma9551_app_reset(struct i2c_client *client, u32 app_mask)
 789{
 790        return mma9551_write_config_byte(client, MMA9551_APPID_RSC,
 791                                         MMA9551_RSC_RESET +
 792                                         MMA9551_RSC_OFFSET(app_mask),
 793                                         MMA9551_RSC_VAL(app_mask));
 794}
 795EXPORT_SYMBOL(mma9551_app_reset);
 796
 797MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>");
 798MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>");
 799MODULE_LICENSE("GPL v2");
 800MODULE_DESCRIPTION("MMA955xL sensors core");
 801