linux/drivers/input/misc/mma8450.c
<<
>>
Prefs
   1/*
   2 *  Driver for Freescale's 3-Axis Accelerometer MMA8450
   3 *
   4 *  Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License as published by
   8 *  the Free Software Foundation; either version 2 of the License, or
   9 *  (at your option) any later version.
  10 *
  11 *  This program is distributed in the hope that it will be useful,
  12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *  GNU General Public License for more details.
  15 *
  16 *  You should have received a copy of the GNU General Public License
  17 *  along with this program; if not, write to the Free Software
  18 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 */
  20
  21#include <linux/kernel.h>
  22#include <linux/module.h>
  23#include <linux/slab.h>
  24#include <linux/delay.h>
  25#include <linux/i2c.h>
  26#include <linux/input-polldev.h>
  27#include <linux/of_device.h>
  28
  29#define MMA8450_DRV_NAME        "mma8450"
  30
  31#define MODE_CHANGE_DELAY_MS    100
  32#define POLL_INTERVAL           100
  33#define POLL_INTERVAL_MAX       500
  34
  35/* register definitions */
  36#define MMA8450_STATUS          0x00
  37#define MMA8450_STATUS_ZXYDR    0x08
  38
  39#define MMA8450_OUT_X8          0x01
  40#define MMA8450_OUT_Y8          0x02
  41#define MMA8450_OUT_Z8          0x03
  42
  43#define MMA8450_OUT_X_LSB       0x05
  44#define MMA8450_OUT_X_MSB       0x06
  45#define MMA8450_OUT_Y_LSB       0x07
  46#define MMA8450_OUT_Y_MSB       0x08
  47#define MMA8450_OUT_Z_LSB       0x09
  48#define MMA8450_OUT_Z_MSB       0x0a
  49
  50#define MMA8450_XYZ_DATA_CFG    0x16
  51
  52#define MMA8450_CTRL_REG1       0x38
  53#define MMA8450_CTRL_REG2       0x39
  54
  55/* mma8450 status */
  56struct mma8450 {
  57        struct i2c_client       *client;
  58        struct input_polled_dev *idev;
  59};
  60
  61static int mma8450_read(struct mma8450 *m, unsigned off)
  62{
  63        struct i2c_client *c = m->client;
  64        int ret;
  65
  66        ret = i2c_smbus_read_byte_data(c, off);
  67        if (ret < 0)
  68                dev_err(&c->dev,
  69                        "failed to read register 0x%02x, error %d\n",
  70                        off, ret);
  71
  72        return ret;
  73}
  74
  75static int mma8450_write(struct mma8450 *m, unsigned off, u8 v)
  76{
  77        struct i2c_client *c = m->client;
  78        int error;
  79
  80        error = i2c_smbus_write_byte_data(c, off, v);
  81        if (error < 0) {
  82                dev_err(&c->dev,
  83                        "failed to write to register 0x%02x, error %d\n",
  84                        off, error);
  85                return error;
  86        }
  87
  88        return 0;
  89}
  90
  91static int mma8450_read_block(struct mma8450 *m, unsigned off,
  92                              u8 *buf, size_t size)
  93{
  94        struct i2c_client *c = m->client;
  95        int err;
  96
  97        err = i2c_smbus_read_i2c_block_data(c, off, size, buf);
  98        if (err < 0) {
  99                dev_err(&c->dev,
 100                        "failed to read block data at 0x%02x, error %d\n",
 101                        MMA8450_OUT_X_LSB, err);
 102                return err;
 103        }
 104
 105        return 0;
 106}
 107
 108static void mma8450_poll(struct input_polled_dev *dev)
 109{
 110        struct mma8450 *m = dev->private;
 111        int x, y, z;
 112        int ret;
 113        u8 buf[6];
 114
 115        ret = mma8450_read(m, MMA8450_STATUS);
 116        if (ret < 0)
 117                return;
 118
 119        if (!(ret & MMA8450_STATUS_ZXYDR))
 120                return;
 121
 122        ret = mma8450_read_block(m, MMA8450_OUT_X_LSB, buf, sizeof(buf));
 123        if (ret < 0)
 124                return;
 125
 126        x = ((int)(s8)buf[1] << 4) | (buf[0] & 0xf);
 127        y = ((int)(s8)buf[3] << 4) | (buf[2] & 0xf);
 128        z = ((int)(s8)buf[5] << 4) | (buf[4] & 0xf);
 129
 130        input_report_abs(dev->input, ABS_X, x);
 131        input_report_abs(dev->input, ABS_Y, y);
 132        input_report_abs(dev->input, ABS_Z, z);
 133        input_sync(dev->input);
 134}
 135
 136/* Initialize the MMA8450 chip */
 137static void mma8450_open(struct input_polled_dev *dev)
 138{
 139        struct mma8450 *m = dev->private;
 140        int err;
 141
 142        /* enable all events from X/Y/Z, no FIFO */
 143        err = mma8450_write(m, MMA8450_XYZ_DATA_CFG, 0x07);
 144        if (err)
 145                return;
 146
 147        /*
 148         * Sleep mode poll rate - 50Hz
 149         * System output data rate - 400Hz
 150         * Full scale selection - Active, +/- 2G
 151         */
 152        err = mma8450_write(m, MMA8450_CTRL_REG1, 0x01);
 153        if (err < 0)
 154                return;
 155
 156        msleep(MODE_CHANGE_DELAY_MS);
 157}
 158
 159static void mma8450_close(struct input_polled_dev *dev)
 160{
 161        struct mma8450 *m = dev->private;
 162
 163        mma8450_write(m, MMA8450_CTRL_REG1, 0x00);
 164        mma8450_write(m, MMA8450_CTRL_REG2, 0x01);
 165}
 166
 167/*
 168 * I2C init/probing/exit functions
 169 */
 170static int mma8450_probe(struct i2c_client *c,
 171                         const struct i2c_device_id *id)
 172{
 173        struct input_polled_dev *idev;
 174        struct mma8450 *m;
 175        int err;
 176
 177        m = devm_kzalloc(&c->dev, sizeof(*m), GFP_KERNEL);
 178        if (!m)
 179                return -ENOMEM;
 180
 181        idev = devm_input_allocate_polled_device(&c->dev);
 182        if (!idev)
 183                return -ENOMEM;
 184
 185        m->client = c;
 186        m->idev = idev;
 187
 188        idev->private           = m;
 189        idev->input->name       = MMA8450_DRV_NAME;
 190        idev->input->id.bustype = BUS_I2C;
 191        idev->poll              = mma8450_poll;
 192        idev->poll_interval     = POLL_INTERVAL;
 193        idev->poll_interval_max = POLL_INTERVAL_MAX;
 194        idev->open              = mma8450_open;
 195        idev->close             = mma8450_close;
 196
 197        __set_bit(EV_ABS, idev->input->evbit);
 198        input_set_abs_params(idev->input, ABS_X, -2048, 2047, 32, 32);
 199        input_set_abs_params(idev->input, ABS_Y, -2048, 2047, 32, 32);
 200        input_set_abs_params(idev->input, ABS_Z, -2048, 2047, 32, 32);
 201
 202        err = input_register_polled_device(idev);
 203        if (err) {
 204                dev_err(&c->dev, "failed to register polled input device\n");
 205                return err;
 206        }
 207
 208        return 0;
 209}
 210
 211static const struct i2c_device_id mma8450_id[] = {
 212        { MMA8450_DRV_NAME, 0 },
 213        { },
 214};
 215MODULE_DEVICE_TABLE(i2c, mma8450_id);
 216
 217static const struct of_device_id mma8450_dt_ids[] = {
 218        { .compatible = "fsl,mma8450", },
 219        { /* sentinel */ }
 220};
 221MODULE_DEVICE_TABLE(of, mma8450_dt_ids);
 222
 223static struct i2c_driver mma8450_driver = {
 224        .driver = {
 225                .name   = MMA8450_DRV_NAME,
 226                .of_match_table = mma8450_dt_ids,
 227        },
 228        .probe          = mma8450_probe,
 229        .id_table       = mma8450_id,
 230};
 231
 232module_i2c_driver(mma8450_driver);
 233
 234MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 235MODULE_DESCRIPTION("MMA8450 3-Axis Accelerometer Driver");
 236MODULE_LICENSE("GPL");
 237