Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * drivers/hwmon/lis3lv02d_i2c.c
0004  *
0005  * Implements I2C interface for lis3lv02d (STMicroelectronics) accelerometer.
0006  * Driver is based on corresponding SPI driver written by Daniel Mack
0007  * (lis3lv02d_spi.c (C) 2009 Daniel Mack <daniel@caiaq.de> ).
0008  *
0009  * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
0010  *
0011  * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
0012  */
0013 
0014 #include <linux/module.h>
0015 #include <linux/kernel.h>
0016 #include <linux/err.h>
0017 #include <linux/i2c.h>
0018 #include <linux/pm_runtime.h>
0019 #include <linux/delay.h>
0020 #include <linux/of.h>
0021 #include <linux/of_platform.h>
0022 #include <linux/of_device.h>
0023 
0024 #include "lis3lv02d.h"
0025 
0026 #define DRV_NAME    "lis3lv02d_i2c"
0027 
0028 static const char reg_vdd[]    = "Vdd";
0029 static const char reg_vdd_io[] = "Vdd_IO";
0030 
0031 static int lis3_reg_ctrl(struct lis3lv02d *lis3, bool state)
0032 {
0033     int ret;
0034     if (state == LIS3_REG_OFF) {
0035         ret = regulator_bulk_disable(ARRAY_SIZE(lis3->regulators),
0036                     lis3->regulators);
0037     } else {
0038         ret = regulator_bulk_enable(ARRAY_SIZE(lis3->regulators),
0039                     lis3->regulators);
0040         /* Chip needs time to wakeup. Not mentioned in datasheet */
0041         usleep_range(10000, 20000);
0042     }
0043     return ret;
0044 }
0045 
0046 static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
0047 {
0048     struct i2c_client *c = lis3->bus_priv;
0049     return i2c_smbus_write_byte_data(c, reg, value);
0050 }
0051 
0052 static inline s32 lis3_i2c_read(struct lis3lv02d *lis3, int reg, u8 *v)
0053 {
0054     struct i2c_client *c = lis3->bus_priv;
0055     *v = i2c_smbus_read_byte_data(c, reg);
0056     return 0;
0057 }
0058 
0059 static inline s32 lis3_i2c_blockread(struct lis3lv02d *lis3, int reg, int len,
0060                 u8 *v)
0061 {
0062     struct i2c_client *c = lis3->bus_priv;
0063     reg |= (1 << 7); /* 7th bit enables address auto incrementation */
0064     return i2c_smbus_read_i2c_block_data(c, reg, len, v);
0065 }
0066 
0067 static int lis3_i2c_init(struct lis3lv02d *lis3)
0068 {
0069     u8 reg;
0070     int ret;
0071 
0072     lis3_reg_ctrl(lis3, LIS3_REG_ON);
0073 
0074     lis3->read(lis3, WHO_AM_I, &reg);
0075     if (reg != lis3->whoami)
0076         printk(KERN_ERR "lis3: power on failure\n");
0077 
0078     /* power up the device */
0079     ret = lis3->read(lis3, CTRL_REG1, &reg);
0080     if (ret < 0)
0081         return ret;
0082 
0083     if (lis3->whoami == WAI_3DLH)
0084         reg |= CTRL1_PM0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
0085     else
0086         reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
0087 
0088     return lis3->write(lis3, CTRL_REG1, reg);
0089 }
0090 
0091 /* Default axis mapping but it can be overwritten by platform data */
0092 static union axis_conversion lis3lv02d_axis_map =
0093     { .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } };
0094 
0095 #ifdef CONFIG_OF
0096 static const struct of_device_id lis3lv02d_i2c_dt_ids[] = {
0097     { .compatible = "st,lis3lv02d" },
0098     {}
0099 };
0100 MODULE_DEVICE_TABLE(of, lis3lv02d_i2c_dt_ids);
0101 #endif
0102 
0103 static int lis3lv02d_i2c_probe(struct i2c_client *client,
0104                     const struct i2c_device_id *id)
0105 {
0106     int ret = 0;
0107     struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
0108 
0109 #ifdef CONFIG_OF
0110     if (of_match_device(lis3lv02d_i2c_dt_ids, &client->dev)) {
0111         lis3_dev.of_node = client->dev.of_node;
0112         ret = lis3lv02d_init_dt(&lis3_dev);
0113         if (ret)
0114             return ret;
0115         pdata = lis3_dev.pdata;
0116     }
0117 #endif
0118 
0119     if (pdata) {
0120         if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
0121             (i2c_check_functionality(client->adapter,
0122                         I2C_FUNC_SMBUS_I2C_BLOCK)))
0123             lis3_dev.blkread  = lis3_i2c_blockread;
0124 
0125         if (pdata->axis_x)
0126             lis3lv02d_axis_map.x = pdata->axis_x;
0127 
0128         if (pdata->axis_y)
0129             lis3lv02d_axis_map.y = pdata->axis_y;
0130 
0131         if (pdata->axis_z)
0132             lis3lv02d_axis_map.z = pdata->axis_z;
0133 
0134         if (pdata->setup_resources)
0135             ret = pdata->setup_resources();
0136 
0137         if (ret)
0138             goto fail;
0139     }
0140 
0141     lis3_dev.regulators[0].supply = reg_vdd;
0142     lis3_dev.regulators[1].supply = reg_vdd_io;
0143     ret = regulator_bulk_get(&client->dev,
0144                  ARRAY_SIZE(lis3_dev.regulators),
0145                  lis3_dev.regulators);
0146     if (ret < 0)
0147         goto fail;
0148 
0149     lis3_dev.pdata    = pdata;
0150     lis3_dev.bus_priv = client;
0151     lis3_dev.init     = lis3_i2c_init;
0152     lis3_dev.read     = lis3_i2c_read;
0153     lis3_dev.write    = lis3_i2c_write;
0154     lis3_dev.irq      = client->irq;
0155     lis3_dev.ac   = lis3lv02d_axis_map;
0156     lis3_dev.pm_dev   = &client->dev;
0157 
0158     i2c_set_clientdata(client, &lis3_dev);
0159 
0160     /* Provide power over the init call */
0161     lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
0162 
0163     ret = lis3lv02d_init_device(&lis3_dev);
0164 
0165     lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
0166 
0167     if (ret)
0168         goto fail2;
0169     return 0;
0170 
0171 fail2:
0172     regulator_bulk_free(ARRAY_SIZE(lis3_dev.regulators),
0173                 lis3_dev.regulators);
0174 fail:
0175     if (pdata && pdata->release_resources)
0176         pdata->release_resources();
0177     return ret;
0178 }
0179 
0180 static int lis3lv02d_i2c_remove(struct i2c_client *client)
0181 {
0182     struct lis3lv02d *lis3 = i2c_get_clientdata(client);
0183     struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
0184 
0185     if (pdata && pdata->release_resources)
0186         pdata->release_resources();
0187 
0188     lis3lv02d_joystick_disable(lis3);
0189     lis3lv02d_remove_fs(&lis3_dev);
0190 
0191     regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
0192                 lis3_dev.regulators);
0193     return 0;
0194 }
0195 
0196 #ifdef CONFIG_PM_SLEEP
0197 static int lis3lv02d_i2c_suspend(struct device *dev)
0198 {
0199     struct i2c_client *client = to_i2c_client(dev);
0200     struct lis3lv02d *lis3 = i2c_get_clientdata(client);
0201 
0202     if (!lis3->pdata || !lis3->pdata->wakeup_flags)
0203         lis3lv02d_poweroff(lis3);
0204     return 0;
0205 }
0206 
0207 static int lis3lv02d_i2c_resume(struct device *dev)
0208 {
0209     struct i2c_client *client = to_i2c_client(dev);
0210     struct lis3lv02d *lis3 = i2c_get_clientdata(client);
0211 
0212     /*
0213      * pm_runtime documentation says that devices should always
0214      * be powered on at resume. Pm_runtime turns them off after system
0215      * wide resume is complete.
0216      */
0217     if (!lis3->pdata || !lis3->pdata->wakeup_flags ||
0218         pm_runtime_suspended(dev))
0219         lis3lv02d_poweron(lis3);
0220 
0221     return 0;
0222 }
0223 #endif /* CONFIG_PM_SLEEP */
0224 
0225 #ifdef CONFIG_PM
0226 static int lis3_i2c_runtime_suspend(struct device *dev)
0227 {
0228     struct i2c_client *client = to_i2c_client(dev);
0229     struct lis3lv02d *lis3 = i2c_get_clientdata(client);
0230 
0231     lis3lv02d_poweroff(lis3);
0232     return 0;
0233 }
0234 
0235 static int lis3_i2c_runtime_resume(struct device *dev)
0236 {
0237     struct i2c_client *client = to_i2c_client(dev);
0238     struct lis3lv02d *lis3 = i2c_get_clientdata(client);
0239 
0240     lis3lv02d_poweron(lis3);
0241     return 0;
0242 }
0243 #endif /* CONFIG_PM */
0244 
0245 static const struct i2c_device_id lis3lv02d_id[] = {
0246     {"lis3lv02d", LIS3LV02D},
0247     {"lis331dlh", LIS331DLH},
0248     {}
0249 };
0250 
0251 MODULE_DEVICE_TABLE(i2c, lis3lv02d_id);
0252 
0253 static const struct dev_pm_ops lis3_pm_ops = {
0254     SET_SYSTEM_SLEEP_PM_OPS(lis3lv02d_i2c_suspend,
0255                 lis3lv02d_i2c_resume)
0256     SET_RUNTIME_PM_OPS(lis3_i2c_runtime_suspend,
0257                lis3_i2c_runtime_resume,
0258                NULL)
0259 };
0260 
0261 static struct i2c_driver lis3lv02d_i2c_driver = {
0262     .driver  = {
0263         .name   = DRV_NAME,
0264         .pm     = &lis3_pm_ops,
0265         .of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids),
0266     },
0267     .probe  = lis3lv02d_i2c_probe,
0268     .remove = lis3lv02d_i2c_remove,
0269     .id_table = lis3lv02d_id,
0270 };
0271 
0272 module_i2c_driver(lis3lv02d_i2c_driver);
0273 
0274 MODULE_AUTHOR("Nokia Corporation");
0275 MODULE_DESCRIPTION("lis3lv02d I2C interface");
0276 MODULE_LICENSE("GPL");