0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/platform_device.h>
0009 #include <linux/input.h>
0010 #include <linux/regulator/consumer.h>
0011 #include <linux/miscdevice.h>
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include <linux/lis3lv02d.h>
0025
0026 enum lis3_reg {
0027 WHO_AM_I = 0x0F,
0028 OFFSET_X = 0x16,
0029 OFFSET_Y = 0x17,
0030 OFFSET_Z = 0x18,
0031 GAIN_X = 0x19,
0032 GAIN_Y = 0x1A,
0033 GAIN_Z = 0x1B,
0034 CTRL_REG1 = 0x20,
0035 CTRL_REG2 = 0x21,
0036 CTRL_REG3 = 0x22,
0037 CTRL_REG4 = 0x23,
0038 HP_FILTER_RESET = 0x23,
0039 STATUS_REG = 0x27,
0040 OUTX_L = 0x28,
0041 OUTX_H = 0x29,
0042 OUTX = 0x29,
0043 OUTY_L = 0x2A,
0044 OUTY_H = 0x2B,
0045 OUTY = 0x2B,
0046 OUTZ_L = 0x2C,
0047 OUTZ_H = 0x2D,
0048 OUTZ = 0x2D,
0049 };
0050
0051 enum lis302d_reg {
0052 FF_WU_CFG_1 = 0x30,
0053 FF_WU_SRC_1 = 0x31,
0054 FF_WU_THS_1 = 0x32,
0055 FF_WU_DURATION_1 = 0x33,
0056 FF_WU_CFG_2 = 0x34,
0057 FF_WU_SRC_2 = 0x35,
0058 FF_WU_THS_2 = 0x36,
0059 FF_WU_DURATION_2 = 0x37,
0060 CLICK_CFG = 0x38,
0061 CLICK_SRC = 0x39,
0062 CLICK_THSY_X = 0x3B,
0063 CLICK_THSZ = 0x3C,
0064 CLICK_TIMELIMIT = 0x3D,
0065 CLICK_LATENCY = 0x3E,
0066 CLICK_WINDOW = 0x3F,
0067 };
0068
0069 enum lis3lv02d_reg {
0070 FF_WU_CFG = 0x30,
0071 FF_WU_SRC = 0x31,
0072 FF_WU_ACK = 0x32,
0073 FF_WU_THS_L = 0x34,
0074 FF_WU_THS_H = 0x35,
0075 FF_WU_DURATION = 0x36,
0076 DD_CFG = 0x38,
0077 DD_SRC = 0x39,
0078 DD_ACK = 0x3A,
0079 DD_THSI_L = 0x3C,
0080 DD_THSI_H = 0x3D,
0081 DD_THSE_L = 0x3E,
0082 DD_THSE_H = 0x3F,
0083 };
0084
0085 enum lis3_who_am_i {
0086 WAI_3DLH = 0x32,
0087 WAI_3DC = 0x33,
0088 WAI_12B = 0x3A,
0089 WAI_8B = 0x3B,
0090 WAI_6B = 0x52,
0091 };
0092
0093 enum lis3_type {
0094 LIS3LV02D,
0095 LIS3DC,
0096 HP3DC,
0097 LIS2302D,
0098 LIS331DLF,
0099 LIS331DLH,
0100 };
0101
0102 enum lis3lv02d_ctrl1_12b {
0103 CTRL1_Xen = 0x01,
0104 CTRL1_Yen = 0x02,
0105 CTRL1_Zen = 0x04,
0106 CTRL1_ST = 0x08,
0107 CTRL1_DF0 = 0x10,
0108 CTRL1_DF1 = 0x20,
0109 CTRL1_PD0 = 0x40,
0110 CTRL1_PD1 = 0x80,
0111 };
0112
0113
0114 enum lis3lv02d_ctrl1_8b {
0115 CTRL1_STM = 0x08,
0116 CTRL1_STP = 0x10,
0117 CTRL1_FS = 0x20,
0118 CTRL1_PD = 0x40,
0119 CTRL1_DR = 0x80,
0120 };
0121
0122 enum lis3lv02d_ctrl1_3dc {
0123 CTRL1_ODR0 = 0x10,
0124 CTRL1_ODR1 = 0x20,
0125 CTRL1_ODR2 = 0x40,
0126 CTRL1_ODR3 = 0x80,
0127 };
0128
0129 enum lis331dlh_ctrl1 {
0130 CTRL1_DR0 = 0x08,
0131 CTRL1_DR1 = 0x10,
0132 CTRL1_PM0 = 0x20,
0133 CTRL1_PM1 = 0x40,
0134 CTRL1_PM2 = 0x80,
0135 };
0136
0137 enum lis331dlh_ctrl2 {
0138 CTRL2_HPEN1 = 0x04,
0139 CTRL2_HPEN2 = 0x08,
0140 CTRL2_FDS_3DLH = 0x10,
0141 CTRL2_BOOT_3DLH = 0x80,
0142 };
0143
0144 enum lis331dlh_ctrl4 {
0145 CTRL4_STSIGN = 0x08,
0146 CTRL4_BLE = 0x40,
0147 CTRL4_BDU = 0x80,
0148 };
0149
0150 enum lis3lv02d_ctrl2 {
0151 CTRL2_DAS = 0x01,
0152 CTRL2_SIM = 0x02,
0153 CTRL2_DRDY = 0x04,
0154 CTRL2_IEN = 0x08,
0155 CTRL2_BOOT = 0x10,
0156 CTRL2_BLE = 0x20,
0157 CTRL2_BDU = 0x40,
0158 CTRL2_FS = 0x80,
0159 };
0160
0161 enum lis3lv02d_ctrl4_3dc {
0162 CTRL4_SIM = 0x01,
0163 CTRL4_ST0 = 0x02,
0164 CTRL4_ST1 = 0x04,
0165 CTRL4_FS0 = 0x10,
0166 CTRL4_FS1 = 0x20,
0167 };
0168
0169 enum lis302d_ctrl2 {
0170 HP_FF_WU2 = 0x08,
0171 HP_FF_WU1 = 0x04,
0172 CTRL2_BOOT_8B = 0x40,
0173 };
0174
0175 enum lis3lv02d_ctrl3 {
0176 CTRL3_CFS0 = 0x01,
0177 CTRL3_CFS1 = 0x02,
0178 CTRL3_FDS = 0x10,
0179 CTRL3_HPFF = 0x20,
0180 CTRL3_HPDD = 0x40,
0181 CTRL3_ECK = 0x80,
0182 };
0183
0184 enum lis3lv02d_status_reg {
0185 STATUS_XDA = 0x01,
0186 STATUS_YDA = 0x02,
0187 STATUS_ZDA = 0x04,
0188 STATUS_XYZDA = 0x08,
0189 STATUS_XOR = 0x10,
0190 STATUS_YOR = 0x20,
0191 STATUS_ZOR = 0x40,
0192 STATUS_XYZOR = 0x80,
0193 };
0194
0195 enum lis3lv02d_ff_wu_cfg {
0196 FF_WU_CFG_XLIE = 0x01,
0197 FF_WU_CFG_XHIE = 0x02,
0198 FF_WU_CFG_YLIE = 0x04,
0199 FF_WU_CFG_YHIE = 0x08,
0200 FF_WU_CFG_ZLIE = 0x10,
0201 FF_WU_CFG_ZHIE = 0x20,
0202 FF_WU_CFG_LIR = 0x40,
0203 FF_WU_CFG_AOI = 0x80,
0204 };
0205
0206 enum lis3lv02d_ff_wu_src {
0207 FF_WU_SRC_XL = 0x01,
0208 FF_WU_SRC_XH = 0x02,
0209 FF_WU_SRC_YL = 0x04,
0210 FF_WU_SRC_YH = 0x08,
0211 FF_WU_SRC_ZL = 0x10,
0212 FF_WU_SRC_ZH = 0x20,
0213 FF_WU_SRC_IA = 0x40,
0214 };
0215
0216 enum lis3lv02d_dd_cfg {
0217 DD_CFG_XLIE = 0x01,
0218 DD_CFG_XHIE = 0x02,
0219 DD_CFG_YLIE = 0x04,
0220 DD_CFG_YHIE = 0x08,
0221 DD_CFG_ZLIE = 0x10,
0222 DD_CFG_ZHIE = 0x20,
0223 DD_CFG_LIR = 0x40,
0224 DD_CFG_IEND = 0x80,
0225 };
0226
0227 enum lis3lv02d_dd_src {
0228 DD_SRC_XL = 0x01,
0229 DD_SRC_XH = 0x02,
0230 DD_SRC_YL = 0x04,
0231 DD_SRC_YH = 0x08,
0232 DD_SRC_ZL = 0x10,
0233 DD_SRC_ZH = 0x20,
0234 DD_SRC_IA = 0x40,
0235 };
0236
0237 enum lis3lv02d_click_src_8b {
0238 CLICK_SINGLE_X = 0x01,
0239 CLICK_DOUBLE_X = 0x02,
0240 CLICK_SINGLE_Y = 0x04,
0241 CLICK_DOUBLE_Y = 0x08,
0242 CLICK_SINGLE_Z = 0x10,
0243 CLICK_DOUBLE_Z = 0x20,
0244 CLICK_IA = 0x40,
0245 };
0246
0247 enum lis3lv02d_reg_state {
0248 LIS3_REG_OFF = 0x00,
0249 LIS3_REG_ON = 0x01,
0250 };
0251
0252 union axis_conversion {
0253 struct {
0254 int x, y, z;
0255 };
0256 int as_array[3];
0257
0258 };
0259
0260 struct lis3lv02d {
0261 void *bus_priv;
0262 struct device *pm_dev;
0263 int (*init) (struct lis3lv02d *lis3);
0264 int (*write) (struct lis3lv02d *lis3, int reg, u8 val);
0265 int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret);
0266 int (*blkread) (struct lis3lv02d *lis3, int reg, int len, u8 *ret);
0267 int (*reg_ctrl) (struct lis3lv02d *lis3, bool state);
0268
0269 int *odrs;
0270 u8 *regs;
0271 int regs_size;
0272 u8 *reg_cache;
0273 bool regs_stored;
0274 u8 odr_mask;
0275 u8 whoami;
0276 s16 (*read_data) (struct lis3lv02d *lis3, int reg);
0277 int mdps_max_val;
0278 int pwron_delay;
0279 int scale;
0280
0281
0282
0283
0284 struct input_dev *idev;
0285 struct platform_device *pdev;
0286 struct regulator_bulk_data regulators[2];
0287 atomic_t count;
0288 union axis_conversion ac;
0289 int mapped_btns[3];
0290
0291 u32 irq;
0292 struct fasync_struct *async_queue;
0293 wait_queue_head_t misc_wait;
0294 unsigned long misc_opened;
0295 struct miscdevice miscdev;
0296
0297 int data_ready_count[2];
0298 atomic_t wake_thread;
0299 unsigned char irq_cfg;
0300 unsigned int shift_adj;
0301
0302 struct lis3lv02d_platform_data *pdata;
0303 struct mutex mutex;
0304
0305 #ifdef CONFIG_OF
0306 struct device_node *of_node;
0307 #endif
0308 };
0309
0310 int lis3lv02d_init_device(struct lis3lv02d *lis3);
0311 int lis3lv02d_joystick_enable(struct lis3lv02d *lis3);
0312 void lis3lv02d_joystick_disable(struct lis3lv02d *lis3);
0313 void lis3lv02d_poweroff(struct lis3lv02d *lis3);
0314 int lis3lv02d_poweron(struct lis3lv02d *lis3);
0315 void lis3lv02d_remove_fs(struct lis3lv02d *lis3);
0316 int lis3lv02d_init_dt(struct lis3lv02d *lis3);
0317
0318 extern struct lis3lv02d lis3_dev;