linux/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
<<
>>
Prefs
   1/*
   2 * drivers/hwmon/lis3lv02d_i2c.c
   3 *
   4 * Implements I2C interface for lis3lv02d (STMicroelectronics) accelerometer.
   5 * Driver is based on corresponding SPI driver written by Daniel Mack
   6 * (lis3lv02d_spi.c (C) 2009 Daniel Mack <daniel@caiaq.de> ).
   7 *
   8 * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
   9 *
  10 * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
  11 *
  12 * This program is free software; you can redistribute it and/or
  13 * modify it under the terms of the GNU General Public License
  14 * version 2 as published by the Free Software Foundation.
  15 *
  16 * This program is distributed in the hope that it will be useful, but
  17 * WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  19 * General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  24 * 02110-1301 USA
  25 */
  26
  27#include <linux/module.h>
  28#include <linux/kernel.h>
  29#include <linux/err.h>
  30#include <linux/i2c.h>
  31#include <linux/pm_runtime.h>
  32#include <linux/delay.h>
  33#include <linux/of.h>
  34#include <linux/of_platform.h>
  35#include <linux/of_device.h>
  36
  37#include "lis3lv02d.h"
  38
  39#define DRV_NAME        "lis3lv02d_i2c"
  40
  41static const char reg_vdd[]    = "Vdd";
  42static const char reg_vdd_io[] = "Vdd_IO";
  43
  44static int lis3_reg_ctrl(struct lis3lv02d *lis3, bool state)
  45{
  46        int ret;
  47        if (state == LIS3_REG_OFF) {
  48                ret = regulator_bulk_disable(ARRAY_SIZE(lis3->regulators),
  49                                        lis3->regulators);
  50        } else {
  51                ret = regulator_bulk_enable(ARRAY_SIZE(lis3->regulators),
  52                                        lis3->regulators);
  53                /* Chip needs time to wakeup. Not mentioned in datasheet */
  54                usleep_range(10000, 20000);
  55        }
  56        return ret;
  57}
  58
  59static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
  60{
  61        struct i2c_client *c = lis3->bus_priv;
  62        return i2c_smbus_write_byte_data(c, reg, value);
  63}
  64
  65static inline s32 lis3_i2c_read(struct lis3lv02d *lis3, int reg, u8 *v)
  66{
  67        struct i2c_client *c = lis3->bus_priv;
  68        *v = i2c_smbus_read_byte_data(c, reg);
  69        return 0;
  70}
  71
  72static inline s32 lis3_i2c_blockread(struct lis3lv02d *lis3, int reg, int len,
  73                                u8 *v)
  74{
  75        struct i2c_client *c = lis3->bus_priv;
  76        reg |= (1 << 7); /* 7th bit enables address auto incrementation */
  77        return i2c_smbus_read_i2c_block_data(c, reg, len, v);
  78}
  79
  80static int lis3_i2c_init(struct lis3lv02d *lis3)
  81{
  82        u8 reg;
  83        int ret;
  84
  85        lis3_reg_ctrl(lis3, LIS3_REG_ON);
  86
  87        lis3->read(lis3, WHO_AM_I, &reg);
  88        if (reg != lis3->whoami)
  89                printk(KERN_ERR "lis3: power on failure\n");
  90
  91        /* power up the device */
  92        ret = lis3->read(lis3, CTRL_REG1, &reg);
  93        if (ret < 0)
  94                return ret;
  95
  96        if (lis3->whoami == WAI_3DLH)
  97                reg |= CTRL1_PM0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
  98        else
  99                reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
 100
 101        return lis3->write(lis3, CTRL_REG1, reg);
 102}
 103
 104/* Default axis mapping but it can be overwritten by platform data */
 105static union axis_conversion lis3lv02d_axis_map =
 106        { .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } };
 107
 108#ifdef CONFIG_OF
 109static const struct of_device_id lis3lv02d_i2c_dt_ids[] = {
 110        { .compatible = "st,lis3lv02d" },
 111        {}
 112};
 113MODULE_DEVICE_TABLE(of, lis3lv02d_i2c_dt_ids);
 114#endif
 115
 116static int lis3lv02d_i2c_probe(struct i2c_client *client,
 117                                        const struct i2c_device_id *id)
 118{
 119        int ret = 0;
 120        struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
 121
 122#ifdef CONFIG_OF
 123        if (of_match_device(lis3lv02d_i2c_dt_ids, &client->dev)) {
 124                lis3_dev.of_node = client->dev.of_node;
 125                ret = lis3lv02d_init_dt(&lis3_dev);
 126                if (ret)
 127                        return ret;
 128                pdata = lis3_dev.pdata;
 129        }
 130#endif
 131
 132        if (pdata) {
 133                if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
 134                        (i2c_check_functionality(client->adapter,
 135                                                I2C_FUNC_SMBUS_I2C_BLOCK)))
 136                        lis3_dev.blkread  = lis3_i2c_blockread;
 137
 138                if (pdata->axis_x)
 139                        lis3lv02d_axis_map.x = pdata->axis_x;
 140
 141                if (pdata->axis_y)
 142                        lis3lv02d_axis_map.y = pdata->axis_y;
 143
 144                if (pdata->axis_z)
 145                        lis3lv02d_axis_map.z = pdata->axis_z;
 146
 147                if (pdata->setup_resources)
 148                        ret = pdata->setup_resources();
 149
 150                if (ret)
 151                        goto fail;
 152        }
 153
 154        lis3_dev.regulators[0].supply = reg_vdd;
 155        lis3_dev.regulators[1].supply = reg_vdd_io;
 156        ret = regulator_bulk_get(&client->dev,
 157                                 ARRAY_SIZE(lis3_dev.regulators),
 158                                 lis3_dev.regulators);
 159        if (ret < 0)
 160                goto fail;
 161
 162        lis3_dev.pdata    = pdata;
 163        lis3_dev.bus_priv = client;
 164        lis3_dev.init     = lis3_i2c_init;
 165        lis3_dev.read     = lis3_i2c_read;
 166        lis3_dev.write    = lis3_i2c_write;
 167        lis3_dev.irq      = client->irq;
 168        lis3_dev.ac       = lis3lv02d_axis_map;
 169        lis3_dev.pm_dev   = &client->dev;
 170
 171        i2c_set_clientdata(client, &lis3_dev);
 172
 173        /* Provide power over the init call */
 174        lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
 175
 176        ret = lis3lv02d_init_device(&lis3_dev);
 177
 178        lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
 179
 180        if (ret)
 181                goto fail2;
 182        return 0;
 183
 184fail2:
 185        regulator_bulk_free(ARRAY_SIZE(lis3_dev.regulators),
 186                                lis3_dev.regulators);
 187fail:
 188        if (pdata && pdata->release_resources)
 189                pdata->release_resources();
 190        return ret;
 191}
 192
 193static int lis3lv02d_i2c_remove(struct i2c_client *client)
 194{
 195        struct lis3lv02d *lis3 = i2c_get_clientdata(client);
 196        struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
 197
 198        if (pdata && pdata->release_resources)
 199                pdata->release_resources();
 200
 201        lis3lv02d_joystick_disable(lis3);
 202        lis3lv02d_remove_fs(&lis3_dev);
 203
 204        regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
 205                            lis3_dev.regulators);
 206        return 0;
 207}
 208
 209#ifdef CONFIG_PM_SLEEP
 210static int lis3lv02d_i2c_suspend(struct device *dev)
 211{
 212        struct i2c_client *client = to_i2c_client(dev);
 213        struct lis3lv02d *lis3 = i2c_get_clientdata(client);
 214
 215        if (!lis3->pdata || !lis3->pdata->wakeup_flags)
 216                lis3lv02d_poweroff(lis3);
 217        return 0;
 218}
 219
 220static int lis3lv02d_i2c_resume(struct device *dev)
 221{
 222        struct i2c_client *client = to_i2c_client(dev);
 223        struct lis3lv02d *lis3 = i2c_get_clientdata(client);
 224
 225        /*
 226         * pm_runtime documentation says that devices should always
 227         * be powered on at resume. Pm_runtime turns them off after system
 228         * wide resume is complete.
 229         */
 230        if (!lis3->pdata || !lis3->pdata->wakeup_flags ||
 231                pm_runtime_suspended(dev))
 232                lis3lv02d_poweron(lis3);
 233
 234        return 0;
 235}
 236#endif /* CONFIG_PM_SLEEP */
 237
 238#ifdef CONFIG_PM
 239static int lis3_i2c_runtime_suspend(struct device *dev)
 240{
 241        struct i2c_client *client = to_i2c_client(dev);
 242        struct lis3lv02d *lis3 = i2c_get_clientdata(client);
 243
 244        lis3lv02d_poweroff(lis3);
 245        return 0;
 246}
 247
 248static int lis3_i2c_runtime_resume(struct device *dev)
 249{
 250        struct i2c_client *client = to_i2c_client(dev);
 251        struct lis3lv02d *lis3 = i2c_get_clientdata(client);
 252
 253        lis3lv02d_poweron(lis3);
 254        return 0;
 255}
 256#endif /* CONFIG_PM */
 257
 258static const struct i2c_device_id lis3lv02d_id[] = {
 259        {"lis3lv02d", LIS3LV02D},
 260        {"lis331dlh", LIS331DLH},
 261        {}
 262};
 263
 264MODULE_DEVICE_TABLE(i2c, lis3lv02d_id);
 265
 266static const struct dev_pm_ops lis3_pm_ops = {
 267        SET_SYSTEM_SLEEP_PM_OPS(lis3lv02d_i2c_suspend,
 268                                lis3lv02d_i2c_resume)
 269        SET_RUNTIME_PM_OPS(lis3_i2c_runtime_suspend,
 270                           lis3_i2c_runtime_resume,
 271                           NULL)
 272};
 273
 274static struct i2c_driver lis3lv02d_i2c_driver = {
 275        .driver  = {
 276                .name   = DRV_NAME,
 277                .pm     = &lis3_pm_ops,
 278                .of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids),
 279        },
 280        .probe  = lis3lv02d_i2c_probe,
 281        .remove = lis3lv02d_i2c_remove,
 282        .id_table = lis3lv02d_id,
 283};
 284
 285module_i2c_driver(lis3lv02d_i2c_driver);
 286
 287MODULE_AUTHOR("Nokia Corporation");
 288MODULE_DESCRIPTION("lis3lv02d I2C interface");
 289MODULE_LICENSE("GPL");
 290