Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  *  lis3lv02d.h - ST LIS3LV02DL accelerometer driver
0004  *
0005  *  Copyright (C) 2007-2008 Yan Burman
0006  *  Copyright (C) 2008-2009 Eric Piel
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  * This driver tries to support the "digital" accelerometer chips from
0015  * STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL,
0016  * LIS331DLH, LIS35DE, or LIS202DL. They are very similar in terms of
0017  * programming, with almost the same registers. In addition to differing
0018  * on physical properties, they differ on the number of axes (2/3),
0019  * precision (8/12 bits), and special features (freefall detection,
0020  * click...). Unfortunately, not all the differences can be probed via
0021  * a register. They can be connected either via I²C or SPI.
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, /* 16 bits: LIS331DLH */
0087     WAI_3DC     = 0x33, /* 8 bits: LIS3DC, HP3DC */
0088     WAI_12B     = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */
0089     WAI_8B      = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
0090     WAI_6B      = 0x52, /* 6 bits: LIS331DLF - not supported */
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 /* Delta to ctrl1_12b version */
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, /* Block Data Update */
0158     CTRL2_FS    = 0x80, /* Full Scale selection */
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; /* used by the bus layer only */
0262     struct device       *pm_dev; /* for pm_runtime purposes */
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;     /* Supported output data rates */
0270     u8          *regs;     /* Regs to store / restore */
0271     int         regs_size;
0272     u8                      *reg_cache;
0273     bool            regs_stored;
0274     u8                      odr_mask;  /* ODR bit mask */
0275     u8          whoami;    /* indicates measurement precision */
0276     s16 (*read_data) (struct lis3lv02d *lis3, int reg);
0277     int         mdps_max_val;
0278     int         pwron_delay;
0279     int                     scale; /*
0280                     * relationship between 1 LBS and mG
0281                     * (1/1000th of earth gravity)
0282                     */
0283 
0284     struct input_dev    *idev;     /* input device */
0285     struct platform_device  *pdev;     /* platform device */
0286     struct regulator_bulk_data regulators[2];
0287     atomic_t        count;     /* interrupt count after last read */
0288     union axis_conversion   ac;        /* hw -> logical axis */
0289     int         mapped_btns[3];
0290 
0291     u32         irq;       /* IRQ number */
0292     struct fasync_struct    *async_queue; /* queue for the misc device */
0293     wait_queue_head_t   misc_wait; /* Wait queue for the misc device */
0294     unsigned long       misc_opened; /* bit0: whether the device is open */
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;  /* for passing board config */
0303     struct mutex        mutex;     /* Serialize poll and selftest */
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;