12b27bdccSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2ff606677SJean Delvare /* 3ff606677SJean Delvare * drivers/hwmon/lis3lv02d_i2c.c 4ff606677SJean Delvare * 5ff606677SJean Delvare * Implements I2C interface for lis3lv02d (STMicroelectronics) accelerometer. 6ff606677SJean Delvare * Driver is based on corresponding SPI driver written by Daniel Mack 7ff606677SJean Delvare * (lis3lv02d_spi.c (C) 2009 Daniel Mack <daniel@caiaq.de> ). 8ff606677SJean Delvare * 9ff606677SJean Delvare * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 10ff606677SJean Delvare * 11ff606677SJean Delvare * Contact: Samu Onkalo <samu.p.onkalo@nokia.com> 12ff606677SJean Delvare */ 13ff606677SJean Delvare 14ff606677SJean Delvare #include <linux/module.h> 15ff606677SJean Delvare #include <linux/kernel.h> 16ff606677SJean Delvare #include <linux/err.h> 17ff606677SJean Delvare #include <linux/i2c.h> 18ff606677SJean Delvare #include <linux/pm_runtime.h> 19ff606677SJean Delvare #include <linux/delay.h> 205dc2db05SAnilKumar Ch #include <linux/of.h> 215dc2db05SAnilKumar Ch #include <linux/of_platform.h> 225dc2db05SAnilKumar Ch #include <linux/of_device.h> 235dc2db05SAnilKumar Ch 24ff606677SJean Delvare #include "lis3lv02d.h" 25ff606677SJean Delvare 26ff606677SJean Delvare #define DRV_NAME "lis3lv02d_i2c" 27ff606677SJean Delvare 28ff606677SJean Delvare static const char reg_vdd[] = "Vdd"; 29ff606677SJean Delvare static const char reg_vdd_io[] = "Vdd_IO"; 30ff606677SJean Delvare 31ff606677SJean Delvare static int lis3_reg_ctrl(struct lis3lv02d *lis3, bool state) 32ff606677SJean Delvare { 33ff606677SJean Delvare int ret; 34ff606677SJean Delvare if (state == LIS3_REG_OFF) { 35ff606677SJean Delvare ret = regulator_bulk_disable(ARRAY_SIZE(lis3->regulators), 36ff606677SJean Delvare lis3->regulators); 37ff606677SJean Delvare } else { 38ff606677SJean Delvare ret = regulator_bulk_enable(ARRAY_SIZE(lis3->regulators), 39ff606677SJean Delvare lis3->regulators); 40ff606677SJean Delvare /* Chip needs time to wakeup. Not mentioned in datasheet */ 41ff606677SJean Delvare usleep_range(10000, 20000); 42ff606677SJean Delvare } 43ff606677SJean Delvare return ret; 44ff606677SJean Delvare } 45ff606677SJean Delvare 46ff606677SJean Delvare static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value) 47ff606677SJean Delvare { 48ff606677SJean Delvare struct i2c_client *c = lis3->bus_priv; 49ff606677SJean Delvare return i2c_smbus_write_byte_data(c, reg, value); 50ff606677SJean Delvare } 51ff606677SJean Delvare 52ff606677SJean Delvare static inline s32 lis3_i2c_read(struct lis3lv02d *lis3, int reg, u8 *v) 53ff606677SJean Delvare { 54ff606677SJean Delvare struct i2c_client *c = lis3->bus_priv; 55ff606677SJean Delvare *v = i2c_smbus_read_byte_data(c, reg); 56ff606677SJean Delvare return 0; 57ff606677SJean Delvare } 58ff606677SJean Delvare 59ff606677SJean Delvare static inline s32 lis3_i2c_blockread(struct lis3lv02d *lis3, int reg, int len, 60ff606677SJean Delvare u8 *v) 61ff606677SJean Delvare { 62ff606677SJean Delvare struct i2c_client *c = lis3->bus_priv; 63ff606677SJean Delvare reg |= (1 << 7); /* 7th bit enables address auto incrementation */ 64ff606677SJean Delvare return i2c_smbus_read_i2c_block_data(c, reg, len, v); 65ff606677SJean Delvare } 66ff606677SJean Delvare 67ff606677SJean Delvare static int lis3_i2c_init(struct lis3lv02d *lis3) 68ff606677SJean Delvare { 69ff606677SJean Delvare u8 reg; 70ff606677SJean Delvare int ret; 71ff606677SJean Delvare 72ff606677SJean Delvare lis3_reg_ctrl(lis3, LIS3_REG_ON); 73ff606677SJean Delvare 74ff606677SJean Delvare lis3->read(lis3, WHO_AM_I, ®); 75ff606677SJean Delvare if (reg != lis3->whoami) 76ff606677SJean Delvare printk(KERN_ERR "lis3: power on failure\n"); 77ff606677SJean Delvare 78ff606677SJean Delvare /* power up the device */ 79ff606677SJean Delvare ret = lis3->read(lis3, CTRL_REG1, ®); 80ff606677SJean Delvare if (ret < 0) 81ff606677SJean Delvare return ret; 82ff606677SJean Delvare 830bf5a8beSAnilKumar Ch if (lis3->whoami == WAI_3DLH) 840bf5a8beSAnilKumar Ch reg |= CTRL1_PM0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen; 850bf5a8beSAnilKumar Ch else 86ff606677SJean Delvare reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen; 870bf5a8beSAnilKumar Ch 88ff606677SJean Delvare return lis3->write(lis3, CTRL_REG1, reg); 89ff606677SJean Delvare } 90ff606677SJean Delvare 91ff606677SJean Delvare /* Default axis mapping but it can be overwritten by platform data */ 92ff606677SJean Delvare static union axis_conversion lis3lv02d_axis_map = 93ff606677SJean Delvare { .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } }; 94ff606677SJean Delvare 955dc2db05SAnilKumar Ch #ifdef CONFIG_OF 966893d9b5SFabian Frederick static const struct of_device_id lis3lv02d_i2c_dt_ids[] = { 975dc2db05SAnilKumar Ch { .compatible = "st,lis3lv02d" }, 985dc2db05SAnilKumar Ch {} 995dc2db05SAnilKumar Ch }; 1005dc2db05SAnilKumar Ch MODULE_DEVICE_TABLE(of, lis3lv02d_i2c_dt_ids); 1015dc2db05SAnilKumar Ch #endif 1025dc2db05SAnilKumar Ch 1037198cf0fSUwe Kleine-König static int lis3lv02d_i2c_probe(struct i2c_client *client) 104ff606677SJean Delvare { 105ff606677SJean Delvare int ret = 0; 106ff606677SJean Delvare struct lis3lv02d_platform_data *pdata = client->dev.platform_data; 107ff606677SJean Delvare 1085dc2db05SAnilKumar Ch #ifdef CONFIG_OF 1095dc2db05SAnilKumar Ch if (of_match_device(lis3lv02d_i2c_dt_ids, &client->dev)) { 1105dc2db05SAnilKumar Ch lis3_dev.of_node = client->dev.of_node; 1115dc2db05SAnilKumar Ch ret = lis3lv02d_init_dt(&lis3_dev); 1125dc2db05SAnilKumar Ch if (ret) 1135dc2db05SAnilKumar Ch return ret; 1145dc2db05SAnilKumar Ch pdata = lis3_dev.pdata; 1155dc2db05SAnilKumar Ch } 1165dc2db05SAnilKumar Ch #endif 1175dc2db05SAnilKumar Ch 118ff606677SJean Delvare if (pdata) { 119ff606677SJean Delvare if ((pdata->driver_features & LIS3_USE_BLOCK_READ) && 120ff606677SJean Delvare (i2c_check_functionality(client->adapter, 121ff606677SJean Delvare I2C_FUNC_SMBUS_I2C_BLOCK))) 122ff606677SJean Delvare lis3_dev.blkread = lis3_i2c_blockread; 123ff606677SJean Delvare 124ff606677SJean Delvare if (pdata->axis_x) 125ff606677SJean Delvare lis3lv02d_axis_map.x = pdata->axis_x; 126ff606677SJean Delvare 127ff606677SJean Delvare if (pdata->axis_y) 128ff606677SJean Delvare lis3lv02d_axis_map.y = pdata->axis_y; 129ff606677SJean Delvare 130ff606677SJean Delvare if (pdata->axis_z) 131ff606677SJean Delvare lis3lv02d_axis_map.z = pdata->axis_z; 132ff606677SJean Delvare 133ff606677SJean Delvare if (pdata->setup_resources) 134ff606677SJean Delvare ret = pdata->setup_resources(); 135ff606677SJean Delvare 136ff606677SJean Delvare if (ret) 137ff606677SJean Delvare goto fail; 138ff606677SJean Delvare } 139ff606677SJean Delvare 140ff606677SJean Delvare lis3_dev.regulators[0].supply = reg_vdd; 141ff606677SJean Delvare lis3_dev.regulators[1].supply = reg_vdd_io; 142ff606677SJean Delvare ret = regulator_bulk_get(&client->dev, 143ff606677SJean Delvare ARRAY_SIZE(lis3_dev.regulators), 144ff606677SJean Delvare lis3_dev.regulators); 145ff606677SJean Delvare if (ret < 0) 146ff606677SJean Delvare goto fail; 147ff606677SJean Delvare 148ff606677SJean Delvare lis3_dev.pdata = pdata; 149ff606677SJean Delvare lis3_dev.bus_priv = client; 150ff606677SJean Delvare lis3_dev.init = lis3_i2c_init; 151ff606677SJean Delvare lis3_dev.read = lis3_i2c_read; 152ff606677SJean Delvare lis3_dev.write = lis3_i2c_write; 153b1b9f7a4SHans de Goede lis3_dev.reg_ctrl = lis3_reg_ctrl; 154ff606677SJean Delvare lis3_dev.irq = client->irq; 155ff606677SJean Delvare lis3_dev.ac = lis3lv02d_axis_map; 156ff606677SJean Delvare lis3_dev.pm_dev = &client->dev; 157ff606677SJean Delvare 158ff606677SJean Delvare i2c_set_clientdata(client, &lis3_dev); 159ff606677SJean Delvare 160ff606677SJean Delvare /* Provide power over the init call */ 161ff606677SJean Delvare lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON); 162ff606677SJean Delvare 163ff606677SJean Delvare ret = lis3lv02d_init_device(&lis3_dev); 164ff606677SJean Delvare 165ff606677SJean Delvare lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF); 166ff606677SJean Delvare 1670021586bSÉric Piel if (ret) 1680021586bSÉric Piel goto fail2; 169ff606677SJean Delvare return 0; 1700021586bSÉric Piel 1710021586bSÉric Piel fail2: 1720021586bSÉric Piel regulator_bulk_free(ARRAY_SIZE(lis3_dev.regulators), 1730021586bSÉric Piel lis3_dev.regulators); 174ff606677SJean Delvare fail: 175ff606677SJean Delvare if (pdata && pdata->release_resources) 176ff606677SJean Delvare pdata->release_resources(); 177ff606677SJean Delvare return ret; 178ff606677SJean Delvare } 179ff606677SJean Delvare 180ed5c2f5fSUwe Kleine-König static void lis3lv02d_i2c_remove(struct i2c_client *client) 181ff606677SJean Delvare { 182ff606677SJean Delvare struct lis3lv02d *lis3 = i2c_get_clientdata(client); 183ff606677SJean Delvare struct lis3lv02d_platform_data *pdata = client->dev.platform_data; 184ff606677SJean Delvare 185ff606677SJean Delvare if (pdata && pdata->release_resources) 186ff606677SJean Delvare pdata->release_resources(); 187ff606677SJean Delvare 188e1e5687dSÉric Piel lis3lv02d_joystick_disable(lis3); 189ff606677SJean Delvare lis3lv02d_remove_fs(&lis3_dev); 190ff606677SJean Delvare 191ff606677SJean Delvare regulator_bulk_free(ARRAY_SIZE(lis3->regulators), 192ff606677SJean Delvare lis3_dev.regulators); 193ff606677SJean Delvare } 194ff606677SJean Delvare 195ff606677SJean Delvare #ifdef CONFIG_PM_SLEEP 196ff606677SJean Delvare static int lis3lv02d_i2c_suspend(struct device *dev) 197ff606677SJean Delvare { 1988c99d8e6SGeliang Tang struct i2c_client *client = to_i2c_client(dev); 199ff606677SJean Delvare struct lis3lv02d *lis3 = i2c_get_clientdata(client); 200ff606677SJean Delvare 201*ac3e0384SHans de Goede /* Turn on for wakeup if turned off by runtime suspend */ 202*ac3e0384SHans de Goede if (lis3->pdata && lis3->pdata->wakeup_flags) { 203*ac3e0384SHans de Goede if (pm_runtime_suspended(dev)) 204*ac3e0384SHans de Goede lis3lv02d_poweron(lis3); 205*ac3e0384SHans de Goede /* For non wakeup turn off if not already turned off by runtime suspend */ 206*ac3e0384SHans de Goede } else if (!pm_runtime_suspended(dev)) 207ff606677SJean Delvare lis3lv02d_poweroff(lis3); 208*ac3e0384SHans de Goede 209ff606677SJean Delvare return 0; 210ff606677SJean Delvare } 211ff606677SJean Delvare 212ff606677SJean Delvare static int lis3lv02d_i2c_resume(struct device *dev) 213ff606677SJean Delvare { 2148c99d8e6SGeliang Tang struct i2c_client *client = to_i2c_client(dev); 215ff606677SJean Delvare struct lis3lv02d *lis3 = i2c_get_clientdata(client); 216ff606677SJean Delvare 217*ac3e0384SHans de Goede /* Turn back off if turned on for wakeup and runtime suspended*/ 218*ac3e0384SHans de Goede if (lis3->pdata && lis3->pdata->wakeup_flags) { 219*ac3e0384SHans de Goede if (pm_runtime_suspended(dev)) 220*ac3e0384SHans de Goede lis3lv02d_poweroff(lis3); 221*ac3e0384SHans de Goede /* For non wakeup turn back on if not runtime suspended */ 222*ac3e0384SHans de Goede } else if (!pm_runtime_suspended(dev)) 223ff606677SJean Delvare lis3lv02d_poweron(lis3); 224ff606677SJean Delvare 225ff606677SJean Delvare return 0; 226ff606677SJean Delvare } 227ff606677SJean Delvare #endif /* CONFIG_PM_SLEEP */ 228ff606677SJean Delvare 229bbd6d050SRafael J. Wysocki #ifdef CONFIG_PM 230ff606677SJean Delvare static int lis3_i2c_runtime_suspend(struct device *dev) 231ff606677SJean Delvare { 2328c99d8e6SGeliang Tang struct i2c_client *client = to_i2c_client(dev); 233ff606677SJean Delvare struct lis3lv02d *lis3 = i2c_get_clientdata(client); 234ff606677SJean Delvare 235ff606677SJean Delvare lis3lv02d_poweroff(lis3); 236ff606677SJean Delvare return 0; 237ff606677SJean Delvare } 238ff606677SJean Delvare 239ff606677SJean Delvare static int lis3_i2c_runtime_resume(struct device *dev) 240ff606677SJean Delvare { 2418c99d8e6SGeliang Tang struct i2c_client *client = to_i2c_client(dev); 242ff606677SJean Delvare struct lis3lv02d *lis3 = i2c_get_clientdata(client); 243ff606677SJean Delvare 244ff606677SJean Delvare lis3lv02d_poweron(lis3); 245ff606677SJean Delvare return 0; 246ff606677SJean Delvare } 247bbd6d050SRafael J. Wysocki #endif /* CONFIG_PM */ 248ff606677SJean Delvare 249ff606677SJean Delvare static const struct i2c_device_id lis3lv02d_id[] = { 250e2b2ed83SAnilKumar Ch {"lis3lv02d", LIS3LV02D}, 2510bf5a8beSAnilKumar Ch {"lis331dlh", LIS331DLH}, 252ff606677SJean Delvare {} 253ff606677SJean Delvare }; 254ff606677SJean Delvare 255ff606677SJean Delvare MODULE_DEVICE_TABLE(i2c, lis3lv02d_id); 256ff606677SJean Delvare 257ff606677SJean Delvare static const struct dev_pm_ops lis3_pm_ops = { 258ff606677SJean Delvare SET_SYSTEM_SLEEP_PM_OPS(lis3lv02d_i2c_suspend, 259ff606677SJean Delvare lis3lv02d_i2c_resume) 260ff606677SJean Delvare SET_RUNTIME_PM_OPS(lis3_i2c_runtime_suspend, 261ff606677SJean Delvare lis3_i2c_runtime_resume, 262ff606677SJean Delvare NULL) 263ff606677SJean Delvare }; 264ff606677SJean Delvare 265ff606677SJean Delvare static struct i2c_driver lis3lv02d_i2c_driver = { 266ff606677SJean Delvare .driver = { 267ff606677SJean Delvare .name = DRV_NAME, 268ff606677SJean Delvare .pm = &lis3_pm_ops, 2695dc2db05SAnilKumar Ch .of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids), 270ff606677SJean Delvare }, 271f050bb8fSUwe Kleine-König .probe = lis3lv02d_i2c_probe, 2722d6bed9cSBill Pemberton .remove = lis3lv02d_i2c_remove, 273ff606677SJean Delvare .id_table = lis3lv02d_id, 274ff606677SJean Delvare }; 275ff606677SJean Delvare 276a64fe2edSAxel Lin module_i2c_driver(lis3lv02d_i2c_driver); 277ff606677SJean Delvare 278ff606677SJean Delvare MODULE_AUTHOR("Nokia Corporation"); 279ff606677SJean Delvare MODULE_DESCRIPTION("lis3lv02d I2C interface"); 280ff606677SJean Delvare MODULE_LICENSE("GPL"); 281