Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * VTI CMA3000_D0x Accelerometer driver
0004  *
0005  * Copyright (C) 2010 Texas Instruments
0006  * Author: Hemanth V <hemanthv@ti.com>
0007  */
0008 
0009 #include <linux/types.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/delay.h>
0012 #include <linux/slab.h>
0013 #include <linux/input.h>
0014 #include <linux/input/cma3000.h>
0015 #include <linux/module.h>
0016 
0017 #include "cma3000_d0x.h"
0018 
0019 #define CMA3000_WHOAMI      0x00
0020 #define CMA3000_REVID       0x01
0021 #define CMA3000_CTRL        0x02
0022 #define CMA3000_STATUS      0x03
0023 #define CMA3000_RSTR        0x04
0024 #define CMA3000_INTSTATUS   0x05
0025 #define CMA3000_DOUTX       0x06
0026 #define CMA3000_DOUTY       0x07
0027 #define CMA3000_DOUTZ       0x08
0028 #define CMA3000_MDTHR       0x09
0029 #define CMA3000_MDFFTMR     0x0A
0030 #define CMA3000_FFTHR       0x0B
0031 
0032 #define CMA3000_RANGE2G    (1 << 7)
0033 #define CMA3000_RANGE8G    (0 << 7)
0034 #define CMA3000_BUSI2C     (0 << 4)
0035 #define CMA3000_MODEMASK   (7 << 1)
0036 #define CMA3000_GRANGEMASK (1 << 7)
0037 
0038 #define CMA3000_STATUS_PERR    1
0039 #define CMA3000_INTSTATUS_FFDET (1 << 2)
0040 
0041 /* Settling time delay in ms */
0042 #define CMA3000_SETDELAY    30
0043 
0044 /* Delay for clearing interrupt in us */
0045 #define CMA3000_INTDELAY    44
0046 
0047 
0048 /*
0049  * Bit weights in mg for bit 0, other bits need
0050  * multiply factor 2^n. Eight bit is the sign bit.
0051  */
0052 #define BIT_TO_2G  18
0053 #define BIT_TO_8G  71
0054 
0055 struct cma3000_accl_data {
0056     const struct cma3000_bus_ops *bus_ops;
0057     const struct cma3000_platform_data *pdata;
0058 
0059     struct device *dev;
0060     struct input_dev *input_dev;
0061 
0062     int bit_to_mg;
0063     int irq;
0064 
0065     int g_range;
0066     u8 mode;
0067 
0068     struct mutex mutex;
0069     bool opened;
0070     bool suspended;
0071 };
0072 
0073 #define CMA3000_READ(data, reg, msg) \
0074     (data->bus_ops->read(data->dev, reg, msg))
0075 #define CMA3000_SET(data, reg, val, msg) \
0076     ((data)->bus_ops->write(data->dev, reg, val, msg))
0077 
0078 /*
0079  * Conversion for each of the eight modes to g, depending
0080  * on G range i.e 2G or 8G. Some modes always operate in
0081  * 8G.
0082  */
0083 
0084 static int mode_to_mg[8][2] = {
0085     { 0, 0 },
0086     { BIT_TO_8G, BIT_TO_2G },
0087     { BIT_TO_8G, BIT_TO_2G },
0088     { BIT_TO_8G, BIT_TO_8G },
0089     { BIT_TO_8G, BIT_TO_8G },
0090     { BIT_TO_8G, BIT_TO_2G },
0091     { BIT_TO_8G, BIT_TO_2G },
0092     { 0, 0},
0093 };
0094 
0095 static void decode_mg(struct cma3000_accl_data *data, int *datax,
0096                 int *datay, int *dataz)
0097 {
0098     /* Data in 2's complement, convert to mg */
0099     *datax = ((s8)*datax) * data->bit_to_mg;
0100     *datay = ((s8)*datay) * data->bit_to_mg;
0101     *dataz = ((s8)*dataz) * data->bit_to_mg;
0102 }
0103 
0104 static irqreturn_t cma3000_thread_irq(int irq, void *dev_id)
0105 {
0106     struct cma3000_accl_data *data = dev_id;
0107     int datax, datay, dataz, intr_status;
0108     u8 ctrl, mode, range;
0109 
0110     intr_status = CMA3000_READ(data, CMA3000_INTSTATUS, "interrupt status");
0111     if (intr_status < 0)
0112         return IRQ_NONE;
0113 
0114     /* Check if free fall is detected, report immediately */
0115     if (intr_status & CMA3000_INTSTATUS_FFDET) {
0116         input_report_abs(data->input_dev, ABS_MISC, 1);
0117         input_sync(data->input_dev);
0118     } else {
0119         input_report_abs(data->input_dev, ABS_MISC, 0);
0120     }
0121 
0122     datax = CMA3000_READ(data, CMA3000_DOUTX, "X");
0123     datay = CMA3000_READ(data, CMA3000_DOUTY, "Y");
0124     dataz = CMA3000_READ(data, CMA3000_DOUTZ, "Z");
0125 
0126     ctrl = CMA3000_READ(data, CMA3000_CTRL, "ctrl");
0127     mode = (ctrl & CMA3000_MODEMASK) >> 1;
0128     range = (ctrl & CMA3000_GRANGEMASK) >> 7;
0129 
0130     data->bit_to_mg = mode_to_mg[mode][range];
0131 
0132     /* Interrupt not for this device */
0133     if (data->bit_to_mg == 0)
0134         return IRQ_NONE;
0135 
0136     /* Decode register values to milli g */
0137     decode_mg(data, &datax, &datay, &dataz);
0138 
0139     input_report_abs(data->input_dev, ABS_X, datax);
0140     input_report_abs(data->input_dev, ABS_Y, datay);
0141     input_report_abs(data->input_dev, ABS_Z, dataz);
0142     input_sync(data->input_dev);
0143 
0144     return IRQ_HANDLED;
0145 }
0146 
0147 static int cma3000_reset(struct cma3000_accl_data *data)
0148 {
0149     int val;
0150 
0151     /* Reset sequence */
0152     CMA3000_SET(data, CMA3000_RSTR, 0x02, "Reset");
0153     CMA3000_SET(data, CMA3000_RSTR, 0x0A, "Reset");
0154     CMA3000_SET(data, CMA3000_RSTR, 0x04, "Reset");
0155 
0156     /* Settling time delay */
0157     mdelay(10);
0158 
0159     val = CMA3000_READ(data, CMA3000_STATUS, "Status");
0160     if (val < 0) {
0161         dev_err(data->dev, "Reset failed\n");
0162         return val;
0163     }
0164 
0165     if (val & CMA3000_STATUS_PERR) {
0166         dev_err(data->dev, "Parity Error\n");
0167         return -EIO;
0168     }
0169 
0170     return 0;
0171 }
0172 
0173 static int cma3000_poweron(struct cma3000_accl_data *data)
0174 {
0175     const struct cma3000_platform_data *pdata = data->pdata;
0176     u8 ctrl = 0;
0177     int ret;
0178 
0179     if (data->g_range == CMARANGE_2G) {
0180         ctrl = (data->mode << 1) | CMA3000_RANGE2G;
0181     } else if (data->g_range == CMARANGE_8G) {
0182         ctrl = (data->mode << 1) | CMA3000_RANGE8G;
0183     } else {
0184         dev_info(data->dev,
0185              "Invalid G range specified, assuming 8G\n");
0186         ctrl = (data->mode << 1) | CMA3000_RANGE8G;
0187     }
0188 
0189     ctrl |= data->bus_ops->ctrl_mod;
0190 
0191     CMA3000_SET(data, CMA3000_MDTHR, pdata->mdthr,
0192             "Motion Detect Threshold");
0193     CMA3000_SET(data, CMA3000_MDFFTMR, pdata->mdfftmr,
0194             "Time register");
0195     CMA3000_SET(data, CMA3000_FFTHR, pdata->ffthr,
0196             "Free fall threshold");
0197     ret = CMA3000_SET(data, CMA3000_CTRL, ctrl, "Mode setting");
0198     if (ret < 0)
0199         return -EIO;
0200 
0201     msleep(CMA3000_SETDELAY);
0202 
0203     return 0;
0204 }
0205 
0206 static int cma3000_poweroff(struct cma3000_accl_data *data)
0207 {
0208     int ret;
0209 
0210     ret = CMA3000_SET(data, CMA3000_CTRL, CMAMODE_POFF, "Mode setting");
0211     msleep(CMA3000_SETDELAY);
0212 
0213     return ret;
0214 }
0215 
0216 static int cma3000_open(struct input_dev *input_dev)
0217 {
0218     struct cma3000_accl_data *data = input_get_drvdata(input_dev);
0219 
0220     mutex_lock(&data->mutex);
0221 
0222     if (!data->suspended)
0223         cma3000_poweron(data);
0224 
0225     data->opened = true;
0226 
0227     mutex_unlock(&data->mutex);
0228 
0229     return 0;
0230 }
0231 
0232 static void cma3000_close(struct input_dev *input_dev)
0233 {
0234     struct cma3000_accl_data *data = input_get_drvdata(input_dev);
0235 
0236     mutex_lock(&data->mutex);
0237 
0238     if (!data->suspended)
0239         cma3000_poweroff(data);
0240 
0241     data->opened = false;
0242 
0243     mutex_unlock(&data->mutex);
0244 }
0245 
0246 void cma3000_suspend(struct cma3000_accl_data *data)
0247 {
0248     mutex_lock(&data->mutex);
0249 
0250     if (!data->suspended && data->opened)
0251         cma3000_poweroff(data);
0252 
0253     data->suspended = true;
0254 
0255     mutex_unlock(&data->mutex);
0256 }
0257 EXPORT_SYMBOL(cma3000_suspend);
0258 
0259 
0260 void cma3000_resume(struct cma3000_accl_data *data)
0261 {
0262     mutex_lock(&data->mutex);
0263 
0264     if (data->suspended && data->opened)
0265         cma3000_poweron(data);
0266 
0267     data->suspended = false;
0268 
0269     mutex_unlock(&data->mutex);
0270 }
0271 EXPORT_SYMBOL(cma3000_resume);
0272 
0273 struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,
0274                        const struct cma3000_bus_ops *bops)
0275 {
0276     const struct cma3000_platform_data *pdata = dev_get_platdata(dev);
0277     struct cma3000_accl_data *data;
0278     struct input_dev *input_dev;
0279     int rev;
0280     int error;
0281 
0282     if (!pdata) {
0283         dev_err(dev, "platform data not found\n");
0284         error = -EINVAL;
0285         goto err_out;
0286     }
0287 
0288 
0289     /* if no IRQ return error */
0290     if (irq == 0) {
0291         error = -EINVAL;
0292         goto err_out;
0293     }
0294 
0295     data = kzalloc(sizeof(struct cma3000_accl_data), GFP_KERNEL);
0296     input_dev = input_allocate_device();
0297     if (!data || !input_dev) {
0298         error = -ENOMEM;
0299         goto err_free_mem;
0300     }
0301 
0302     data->dev = dev;
0303     data->input_dev = input_dev;
0304     data->bus_ops = bops;
0305     data->pdata = pdata;
0306     data->irq = irq;
0307     mutex_init(&data->mutex);
0308 
0309     data->mode = pdata->mode;
0310     if (data->mode > CMAMODE_POFF) {
0311         data->mode = CMAMODE_MOTDET;
0312         dev_warn(dev,
0313              "Invalid mode specified, assuming Motion Detect\n");
0314     }
0315 
0316     data->g_range = pdata->g_range;
0317     if (data->g_range != CMARANGE_2G && data->g_range != CMARANGE_8G) {
0318         dev_info(dev,
0319              "Invalid G range specified, assuming 8G\n");
0320         data->g_range = CMARANGE_8G;
0321     }
0322 
0323     input_dev->name = "cma3000-accelerometer";
0324     input_dev->id.bustype = bops->bustype;
0325     input_dev->open = cma3000_open;
0326     input_dev->close = cma3000_close;
0327 
0328      __set_bit(EV_ABS, input_dev->evbit);
0329 
0330     input_set_abs_params(input_dev, ABS_X,
0331             -data->g_range, data->g_range, pdata->fuzz_x, 0);
0332     input_set_abs_params(input_dev, ABS_Y,
0333             -data->g_range, data->g_range, pdata->fuzz_y, 0);
0334     input_set_abs_params(input_dev, ABS_Z,
0335             -data->g_range, data->g_range, pdata->fuzz_z, 0);
0336     input_set_abs_params(input_dev, ABS_MISC, 0, 1, 0, 0);
0337 
0338     input_set_drvdata(input_dev, data);
0339 
0340     error = cma3000_reset(data);
0341     if (error)
0342         goto err_free_mem;
0343 
0344     rev = CMA3000_READ(data, CMA3000_REVID, "Revid");
0345     if (rev < 0) {
0346         error = rev;
0347         goto err_free_mem;
0348     }
0349 
0350     pr_info("CMA3000 Accelerometer: Revision %x\n", rev);
0351 
0352     error = request_threaded_irq(irq, NULL, cma3000_thread_irq,
0353                      pdata->irqflags | IRQF_ONESHOT,
0354                      "cma3000_d0x", data);
0355     if (error) {
0356         dev_err(dev, "request_threaded_irq failed\n");
0357         goto err_free_mem;
0358     }
0359 
0360     error = input_register_device(data->input_dev);
0361     if (error) {
0362         dev_err(dev, "Unable to register input device\n");
0363         goto err_free_irq;
0364     }
0365 
0366     return data;
0367 
0368 err_free_irq:
0369     free_irq(irq, data);
0370 err_free_mem:
0371     input_free_device(input_dev);
0372     kfree(data);
0373 err_out:
0374     return ERR_PTR(error);
0375 }
0376 EXPORT_SYMBOL(cma3000_init);
0377 
0378 void cma3000_exit(struct cma3000_accl_data *data)
0379 {
0380     free_irq(data->irq, data);
0381     input_unregister_device(data->input_dev);
0382     kfree(data);
0383 }
0384 EXPORT_SYMBOL(cma3000_exit);
0385 
0386 MODULE_DESCRIPTION("CMA3000-D0x Accelerometer Driver");
0387 MODULE_LICENSE("GPL");
0388 MODULE_AUTHOR("Hemanth V <hemanthv@ti.com>");