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/init.h> 30 #include <linux/err.h> 31 #include <linux/i2c.h> 32 #include <linux/pm_runtime.h> 33 #include <linux/delay.h> 34 #include <linux/of.h> 35 #include <linux/of_platform.h> 36 #include <linux/of_device.h> 37 38 #include "lis3lv02d.h" 39 40 #define DRV_NAME "lis3lv02d_i2c" 41 42 static const char reg_vdd[] = "Vdd"; 43 static const char reg_vdd_io[] = "Vdd_IO"; 44 45 static int lis3_reg_ctrl(struct lis3lv02d *lis3, bool state) 46 { 47 int ret; 48 if (state == LIS3_REG_OFF) { 49 ret = regulator_bulk_disable(ARRAY_SIZE(lis3->regulators), 50 lis3->regulators); 51 } else { 52 ret = regulator_bulk_enable(ARRAY_SIZE(lis3->regulators), 53 lis3->regulators); 54 /* Chip needs time to wakeup. Not mentioned in datasheet */ 55 usleep_range(10000, 20000); 56 } 57 return ret; 58 } 59 60 static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value) 61 { 62 struct i2c_client *c = lis3->bus_priv; 63 return i2c_smbus_write_byte_data(c, reg, value); 64 } 65 66 static inline s32 lis3_i2c_read(struct lis3lv02d *lis3, int reg, u8 *v) 67 { 68 struct i2c_client *c = lis3->bus_priv; 69 *v = i2c_smbus_read_byte_data(c, reg); 70 return 0; 71 } 72 73 static inline s32 lis3_i2c_blockread(struct lis3lv02d *lis3, int reg, int len, 74 u8 *v) 75 { 76 struct i2c_client *c = lis3->bus_priv; 77 reg |= (1 << 7); /* 7th bit enables address auto incrementation */ 78 return i2c_smbus_read_i2c_block_data(c, reg, len, v); 79 } 80 81 static int lis3_i2c_init(struct lis3lv02d *lis3) 82 { 83 u8 reg; 84 int ret; 85 86 lis3_reg_ctrl(lis3, LIS3_REG_ON); 87 88 lis3->read(lis3, WHO_AM_I, ®); 89 if (reg != lis3->whoami) 90 printk(KERN_ERR "lis3: power on failure\n"); 91 92 /* power up the device */ 93 ret = lis3->read(lis3, CTRL_REG1, ®); 94 if (ret < 0) 95 return ret; 96 97 if (lis3->whoami == WAI_3DLH) 98 reg |= CTRL1_PM0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen; 99 else 100 reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen; 101 102 return lis3->write(lis3, CTRL_REG1, reg); 103 } 104 105 /* Default axis mapping but it can be overwritten by platform data */ 106 static union axis_conversion lis3lv02d_axis_map = 107 { .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } }; 108 109 #ifdef CONFIG_OF 110 static struct of_device_id lis3lv02d_i2c_dt_ids[] = { 111 { .compatible = "st,lis3lv02d" }, 112 {} 113 }; 114 MODULE_DEVICE_TABLE(of, lis3lv02d_i2c_dt_ids); 115 #endif 116 117 static int lis3lv02d_i2c_probe(struct i2c_client *client, 118 const struct i2c_device_id *id) 119 { 120 int ret = 0; 121 struct lis3lv02d_platform_data *pdata = client->dev.platform_data; 122 123 #ifdef CONFIG_OF 124 if (of_match_device(lis3lv02d_i2c_dt_ids, &client->dev)) { 125 lis3_dev.of_node = client->dev.of_node; 126 ret = lis3lv02d_init_dt(&lis3_dev); 127 if (ret) 128 return ret; 129 pdata = lis3_dev.pdata; 130 } 131 #endif 132 133 if (pdata) { 134 if ((pdata->driver_features & LIS3_USE_BLOCK_READ) && 135 (i2c_check_functionality(client->adapter, 136 I2C_FUNC_SMBUS_I2C_BLOCK))) 137 lis3_dev.blkread = lis3_i2c_blockread; 138 139 if (pdata->axis_x) 140 lis3lv02d_axis_map.x = pdata->axis_x; 141 142 if (pdata->axis_y) 143 lis3lv02d_axis_map.y = pdata->axis_y; 144 145 if (pdata->axis_z) 146 lis3lv02d_axis_map.z = pdata->axis_z; 147 148 if (pdata->setup_resources) 149 ret = pdata->setup_resources(); 150 151 if (ret) 152 goto fail; 153 } 154 155 lis3_dev.regulators[0].supply = reg_vdd; 156 lis3_dev.regulators[1].supply = reg_vdd_io; 157 ret = regulator_bulk_get(&client->dev, 158 ARRAY_SIZE(lis3_dev.regulators), 159 lis3_dev.regulators); 160 if (ret < 0) 161 goto fail; 162 163 lis3_dev.pdata = pdata; 164 lis3_dev.bus_priv = client; 165 lis3_dev.init = lis3_i2c_init; 166 lis3_dev.read = lis3_i2c_read; 167 lis3_dev.write = lis3_i2c_write; 168 lis3_dev.irq = client->irq; 169 lis3_dev.ac = lis3lv02d_axis_map; 170 lis3_dev.pm_dev = &client->dev; 171 172 i2c_set_clientdata(client, &lis3_dev); 173 174 /* Provide power over the init call */ 175 lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON); 176 177 ret = lis3lv02d_init_device(&lis3_dev); 178 179 lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF); 180 181 if (ret) 182 goto fail2; 183 return 0; 184 185 fail2: 186 regulator_bulk_free(ARRAY_SIZE(lis3_dev.regulators), 187 lis3_dev.regulators); 188 fail: 189 if (pdata && pdata->release_resources) 190 pdata->release_resources(); 191 return ret; 192 } 193 194 static int lis3lv02d_i2c_remove(struct i2c_client *client) 195 { 196 struct lis3lv02d *lis3 = i2c_get_clientdata(client); 197 struct lis3lv02d_platform_data *pdata = client->dev.platform_data; 198 199 if (pdata && pdata->release_resources) 200 pdata->release_resources(); 201 202 lis3lv02d_joystick_disable(lis3); 203 lis3lv02d_remove_fs(&lis3_dev); 204 205 regulator_bulk_free(ARRAY_SIZE(lis3->regulators), 206 lis3_dev.regulators); 207 return 0; 208 } 209 210 #ifdef CONFIG_PM_SLEEP 211 static int lis3lv02d_i2c_suspend(struct device *dev) 212 { 213 struct i2c_client *client = container_of(dev, struct i2c_client, dev); 214 struct lis3lv02d *lis3 = i2c_get_clientdata(client); 215 216 if (!lis3->pdata || !lis3->pdata->wakeup_flags) 217 lis3lv02d_poweroff(lis3); 218 return 0; 219 } 220 221 static int lis3lv02d_i2c_resume(struct device *dev) 222 { 223 struct i2c_client *client = container_of(dev, struct i2c_client, dev); 224 struct lis3lv02d *lis3 = i2c_get_clientdata(client); 225 226 /* 227 * pm_runtime documentation says that devices should always 228 * be powered on at resume. Pm_runtime turns them off after system 229 * wide resume is complete. 230 */ 231 if (!lis3->pdata || !lis3->pdata->wakeup_flags || 232 pm_runtime_suspended(dev)) 233 lis3lv02d_poweron(lis3); 234 235 return 0; 236 } 237 #endif /* CONFIG_PM_SLEEP */ 238 239 #ifdef CONFIG_PM_RUNTIME 240 static int lis3_i2c_runtime_suspend(struct device *dev) 241 { 242 struct i2c_client *client = container_of(dev, struct i2c_client, dev); 243 struct lis3lv02d *lis3 = i2c_get_clientdata(client); 244 245 lis3lv02d_poweroff(lis3); 246 return 0; 247 } 248 249 static int lis3_i2c_runtime_resume(struct device *dev) 250 { 251 struct i2c_client *client = container_of(dev, struct i2c_client, dev); 252 struct lis3lv02d *lis3 = i2c_get_clientdata(client); 253 254 lis3lv02d_poweron(lis3); 255 return 0; 256 } 257 #endif /* CONFIG_PM_RUNTIME */ 258 259 static const struct i2c_device_id lis3lv02d_id[] = { 260 {"lis3lv02d", LIS3LV02D}, 261 {"lis331dlh", LIS331DLH}, 262 {} 263 }; 264 265 MODULE_DEVICE_TABLE(i2c, lis3lv02d_id); 266 267 static const struct dev_pm_ops lis3_pm_ops = { 268 SET_SYSTEM_SLEEP_PM_OPS(lis3lv02d_i2c_suspend, 269 lis3lv02d_i2c_resume) 270 SET_RUNTIME_PM_OPS(lis3_i2c_runtime_suspend, 271 lis3_i2c_runtime_resume, 272 NULL) 273 }; 274 275 static struct i2c_driver lis3lv02d_i2c_driver = { 276 .driver = { 277 .name = DRV_NAME, 278 .owner = THIS_MODULE, 279 .pm = &lis3_pm_ops, 280 .of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids), 281 }, 282 .probe = lis3lv02d_i2c_probe, 283 .remove = lis3lv02d_i2c_remove, 284 .id_table = lis3lv02d_id, 285 }; 286 287 module_i2c_driver(lis3lv02d_i2c_driver); 288 289 MODULE_AUTHOR("Nokia Corporation"); 290 MODULE_DESCRIPTION("lis3lv02d I2C interface"); 291 MODULE_LICENSE("GPL"); 292