1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * lis3lv02d.h - ST LIS3LV02DL accelerometer driver 4 * 5 * Copyright (C) 2007-2008 Yan Burman 6 * Copyright (C) 2008-2009 Eric Piel 7 */ 8 #include <linux/platform_device.h> 9 #include <linux/input.h> 10 #include <linux/regulator/consumer.h> 11 #include <linux/miscdevice.h> 12 13 /* 14 * This driver tries to support the "digital" accelerometer chips from 15 * STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL, 16 * LIS331DLH, LIS35DE, or LIS202DL. They are very similar in terms of 17 * programming, with almost the same registers. In addition to differing 18 * on physical properties, they differ on the number of axes (2/3), 19 * precision (8/12 bits), and special features (freefall detection, 20 * click...). Unfortunately, not all the differences can be probed via 21 * a register. They can be connected either via I²C or SPI. 22 */ 23 24 #include <linux/lis3lv02d.h> 25 26 enum lis3_reg { 27 WHO_AM_I = 0x0F, 28 OFFSET_X = 0x16, 29 OFFSET_Y = 0x17, 30 OFFSET_Z = 0x18, 31 GAIN_X = 0x19, 32 GAIN_Y = 0x1A, 33 GAIN_Z = 0x1B, 34 CTRL_REG1 = 0x20, 35 CTRL_REG2 = 0x21, 36 CTRL_REG3 = 0x22, 37 CTRL_REG4 = 0x23, 38 HP_FILTER_RESET = 0x23, 39 STATUS_REG = 0x27, 40 OUTX_L = 0x28, 41 OUTX_H = 0x29, 42 OUTX = 0x29, 43 OUTY_L = 0x2A, 44 OUTY_H = 0x2B, 45 OUTY = 0x2B, 46 OUTZ_L = 0x2C, 47 OUTZ_H = 0x2D, 48 OUTZ = 0x2D, 49 }; 50 51 enum lis302d_reg { 52 FF_WU_CFG_1 = 0x30, 53 FF_WU_SRC_1 = 0x31, 54 FF_WU_THS_1 = 0x32, 55 FF_WU_DURATION_1 = 0x33, 56 FF_WU_CFG_2 = 0x34, 57 FF_WU_SRC_2 = 0x35, 58 FF_WU_THS_2 = 0x36, 59 FF_WU_DURATION_2 = 0x37, 60 CLICK_CFG = 0x38, 61 CLICK_SRC = 0x39, 62 CLICK_THSY_X = 0x3B, 63 CLICK_THSZ = 0x3C, 64 CLICK_TIMELIMIT = 0x3D, 65 CLICK_LATENCY = 0x3E, 66 CLICK_WINDOW = 0x3F, 67 }; 68 69 enum lis3lv02d_reg { 70 FF_WU_CFG = 0x30, 71 FF_WU_SRC = 0x31, 72 FF_WU_ACK = 0x32, 73 FF_WU_THS_L = 0x34, 74 FF_WU_THS_H = 0x35, 75 FF_WU_DURATION = 0x36, 76 DD_CFG = 0x38, 77 DD_SRC = 0x39, 78 DD_ACK = 0x3A, 79 DD_THSI_L = 0x3C, 80 DD_THSI_H = 0x3D, 81 DD_THSE_L = 0x3E, 82 DD_THSE_H = 0x3F, 83 }; 84 85 enum lis3_who_am_i { 86 WAI_3DLH = 0x32, /* 16 bits: LIS331DLH */ 87 WAI_3DC = 0x33, /* 8 bits: LIS3DC, HP3DC */ 88 WAI_12B = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */ 89 WAI_8B = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */ 90 WAI_6B = 0x52, /* 6 bits: LIS331DLF - not supported */ 91 }; 92 93 enum lis3_type { 94 LIS3LV02D, 95 LIS3DC, 96 HP3DC, 97 LIS2302D, 98 LIS331DLF, 99 LIS331DLH, 100 }; 101 102 enum lis3lv02d_ctrl1_12b { 103 CTRL1_Xen = 0x01, 104 CTRL1_Yen = 0x02, 105 CTRL1_Zen = 0x04, 106 CTRL1_ST = 0x08, 107 CTRL1_DF0 = 0x10, 108 CTRL1_DF1 = 0x20, 109 CTRL1_PD0 = 0x40, 110 CTRL1_PD1 = 0x80, 111 }; 112 113 /* Delta to ctrl1_12b version */ 114 enum lis3lv02d_ctrl1_8b { 115 CTRL1_STM = 0x08, 116 CTRL1_STP = 0x10, 117 CTRL1_FS = 0x20, 118 CTRL1_PD = 0x40, 119 CTRL1_DR = 0x80, 120 }; 121 122 enum lis3lv02d_ctrl1_3dc { 123 CTRL1_ODR0 = 0x10, 124 CTRL1_ODR1 = 0x20, 125 CTRL1_ODR2 = 0x40, 126 CTRL1_ODR3 = 0x80, 127 }; 128 129 enum lis331dlh_ctrl1 { 130 CTRL1_DR0 = 0x08, 131 CTRL1_DR1 = 0x10, 132 CTRL1_PM0 = 0x20, 133 CTRL1_PM1 = 0x40, 134 CTRL1_PM2 = 0x80, 135 }; 136 137 enum lis331dlh_ctrl2 { 138 CTRL2_HPEN1 = 0x04, 139 CTRL2_HPEN2 = 0x08, 140 CTRL2_FDS_3DLH = 0x10, 141 CTRL2_BOOT_3DLH = 0x80, 142 }; 143 144 enum lis331dlh_ctrl4 { 145 CTRL4_STSIGN = 0x08, 146 CTRL4_BLE = 0x40, 147 CTRL4_BDU = 0x80, 148 }; 149 150 enum lis3lv02d_ctrl2 { 151 CTRL2_DAS = 0x01, 152 CTRL2_SIM = 0x02, 153 CTRL2_DRDY = 0x04, 154 CTRL2_IEN = 0x08, 155 CTRL2_BOOT = 0x10, 156 CTRL2_BLE = 0x20, 157 CTRL2_BDU = 0x40, /* Block Data Update */ 158 CTRL2_FS = 0x80, /* Full Scale selection */ 159 }; 160 161 enum lis3lv02d_ctrl4_3dc { 162 CTRL4_SIM = 0x01, 163 CTRL4_ST0 = 0x02, 164 CTRL4_ST1 = 0x04, 165 CTRL4_FS0 = 0x10, 166 CTRL4_FS1 = 0x20, 167 }; 168 169 enum lis302d_ctrl2 { 170 HP_FF_WU2 = 0x08, 171 HP_FF_WU1 = 0x04, 172 CTRL2_BOOT_8B = 0x40, 173 }; 174 175 enum lis3lv02d_ctrl3 { 176 CTRL3_CFS0 = 0x01, 177 CTRL3_CFS1 = 0x02, 178 CTRL3_FDS = 0x10, 179 CTRL3_HPFF = 0x20, 180 CTRL3_HPDD = 0x40, 181 CTRL3_ECK = 0x80, 182 }; 183 184 enum lis3lv02d_status_reg { 185 STATUS_XDA = 0x01, 186 STATUS_YDA = 0x02, 187 STATUS_ZDA = 0x04, 188 STATUS_XYZDA = 0x08, 189 STATUS_XOR = 0x10, 190 STATUS_YOR = 0x20, 191 STATUS_ZOR = 0x40, 192 STATUS_XYZOR = 0x80, 193 }; 194 195 enum lis3lv02d_ff_wu_cfg { 196 FF_WU_CFG_XLIE = 0x01, 197 FF_WU_CFG_XHIE = 0x02, 198 FF_WU_CFG_YLIE = 0x04, 199 FF_WU_CFG_YHIE = 0x08, 200 FF_WU_CFG_ZLIE = 0x10, 201 FF_WU_CFG_ZHIE = 0x20, 202 FF_WU_CFG_LIR = 0x40, 203 FF_WU_CFG_AOI = 0x80, 204 }; 205 206 enum lis3lv02d_ff_wu_src { 207 FF_WU_SRC_XL = 0x01, 208 FF_WU_SRC_XH = 0x02, 209 FF_WU_SRC_YL = 0x04, 210 FF_WU_SRC_YH = 0x08, 211 FF_WU_SRC_ZL = 0x10, 212 FF_WU_SRC_ZH = 0x20, 213 FF_WU_SRC_IA = 0x40, 214 }; 215 216 enum lis3lv02d_dd_cfg { 217 DD_CFG_XLIE = 0x01, 218 DD_CFG_XHIE = 0x02, 219 DD_CFG_YLIE = 0x04, 220 DD_CFG_YHIE = 0x08, 221 DD_CFG_ZLIE = 0x10, 222 DD_CFG_ZHIE = 0x20, 223 DD_CFG_LIR = 0x40, 224 DD_CFG_IEND = 0x80, 225 }; 226 227 enum lis3lv02d_dd_src { 228 DD_SRC_XL = 0x01, 229 DD_SRC_XH = 0x02, 230 DD_SRC_YL = 0x04, 231 DD_SRC_YH = 0x08, 232 DD_SRC_ZL = 0x10, 233 DD_SRC_ZH = 0x20, 234 DD_SRC_IA = 0x40, 235 }; 236 237 enum lis3lv02d_click_src_8b { 238 CLICK_SINGLE_X = 0x01, 239 CLICK_DOUBLE_X = 0x02, 240 CLICK_SINGLE_Y = 0x04, 241 CLICK_DOUBLE_Y = 0x08, 242 CLICK_SINGLE_Z = 0x10, 243 CLICK_DOUBLE_Z = 0x20, 244 CLICK_IA = 0x40, 245 }; 246 247 enum lis3lv02d_reg_state { 248 LIS3_REG_OFF = 0x00, 249 LIS3_REG_ON = 0x01, 250 }; 251 252 union axis_conversion { 253 struct { 254 int x, y, z; 255 }; 256 int as_array[3]; 257 258 }; 259 260 struct lis3lv02d { 261 void *bus_priv; /* used by the bus layer only */ 262 struct device *pm_dev; /* for pm_runtime purposes */ 263 int (*init) (struct lis3lv02d *lis3); 264 int (*write) (struct lis3lv02d *lis3, int reg, u8 val); 265 int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret); 266 int (*blkread) (struct lis3lv02d *lis3, int reg, int len, u8 *ret); 267 int (*reg_ctrl) (struct lis3lv02d *lis3, bool state); 268 269 int *odrs; /* Supported output data rates */ 270 u8 *regs; /* Regs to store / restore */ 271 int regs_size; 272 u8 *reg_cache; 273 bool regs_stored; 274 u8 odr_mask; /* ODR bit mask */ 275 u8 whoami; /* indicates measurement precision */ 276 s16 (*read_data) (struct lis3lv02d *lis3, int reg); 277 int mdps_max_val; 278 int pwron_delay; 279 int scale; /* 280 * relationship between 1 LBS and mG 281 * (1/1000th of earth gravity) 282 */ 283 284 struct input_dev *idev; /* input device */ 285 struct platform_device *pdev; /* platform device */ 286 struct regulator_bulk_data regulators[2]; 287 atomic_t count; /* interrupt count after last read */ 288 union axis_conversion ac; /* hw -> logical axis */ 289 int mapped_btns[3]; 290 291 u32 irq; /* IRQ number */ 292 struct fasync_struct *async_queue; /* queue for the misc device */ 293 wait_queue_head_t misc_wait; /* Wait queue for the misc device */ 294 unsigned long misc_opened; /* bit0: whether the device is open */ 295 struct miscdevice miscdev; 296 297 int data_ready_count[2]; 298 atomic_t wake_thread; 299 unsigned char irq_cfg; 300 unsigned int shift_adj; 301 302 struct lis3lv02d_platform_data *pdata; /* for passing board config */ 303 struct mutex mutex; /* Serialize poll and selftest */ 304 305 #ifdef CONFIG_OF 306 struct device_node *of_node; 307 #endif 308 }; 309 310 int lis3lv02d_init_device(struct lis3lv02d *lis3); 311 int lis3lv02d_joystick_enable(struct lis3lv02d *lis3); 312 void lis3lv02d_joystick_disable(struct lis3lv02d *lis3); 313 void lis3lv02d_poweroff(struct lis3lv02d *lis3); 314 int lis3lv02d_poweron(struct lis3lv02d *lis3); 315 void lis3lv02d_remove_fs(struct lis3lv02d *lis3); 316 int lis3lv02d_init_dt(struct lis3lv02d *lis3); 317 318 extern struct lis3lv02d lis3_dev; 319